Merge branch '3.0' of github.com:taosdata/TDengine into szhou/pseudo-column-aliasname
This commit is contained in:
commit
b78a32eb1a
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -56,7 +56,7 @@ database_option: {
|
|||
- WAL_FSYNC_PERIOD: specifies the interval (in milliseconds) at which data is written from the WAL to disk. This parameter takes effect only when the WAL parameter is set to 2. The default value is 3000. Enter a value between 0 and 180000. The value 0 indicates that incoming data is immediately written to disk.
|
||||
- MAXROWS: specifies the maximum number of rows recorded in a block. The default value is 4096.
|
||||
- MINROWS: specifies the minimum number of rows recorded in a block. The default value is 100.
|
||||
- KEEP: specifies the time for which data is retained. Enter a value between 1 and 365000. The default value is 3650. The value of the KEEP parameter must be greater than or equal to the value of the DURATION parameter. TDengine automatically deletes data that is older than the value of the KEEP parameter. You can use m (minutes), h (hours), and d (days) as the unit, for example KEEP 100h or KEEP 10d. If you do not include a unit, d is used by default. TDengine Enterprise supports [Tiered Storage](https://docs.tdengine.com/tdinternal/arch/#tiered-storage) function, thus multiple KEEP values (comma separated and up to 3 values supported, and meet keep 0 <= keep 1 <= keep 2, e.g. KEEP 100h,100d,3650d) are supported; TDengine OSS does not support Tiered Storage function (although multiple keep values are configured, they do not take effect, only the maximum keep value is used as KEEP).
|
||||
- KEEP: specifies the time for which data is retained. Enter a value between 1 and 365000. The default value is 3650. The value of the KEEP parameter must be greater than or equal to three times of the value of the DURATION parameter. TDengine automatically deletes data that is older than the value of the KEEP parameter. You can use m (minutes), h (hours), and d (days) as the unit, for example KEEP 100h or KEEP 10d. If you do not include a unit, d is used by default. TDengine Enterprise supports [Tiered Storage](https://docs.tdengine.com/tdinternal/arch/#tiered-storage) function, thus multiple KEEP values (comma separated and up to 3 values supported, and meet keep 0 <= keep 1 <= keep 2, e.g. KEEP 100h,100d,3650d) are supported; TDengine OSS does not support Tiered Storage function (although multiple keep values are configured, they do not take effect, only the maximum keep value is used as KEEP).
|
||||
- PAGES: specifies the number of pages in the metadata storage engine cache on each vnode. Enter a value greater than or equal to 64. The default value is 256. The space occupied by metadata storage on each vnode is equal to the product of the values of the PAGESIZE and PAGES parameters. The space occupied by default is 1 MB.
|
||||
- PAGESIZE: specifies the size (in KB) of each page in the metadata storage engine cache on each vnode. The default value is 4. Enter a value between 1 and 16384.
|
||||
- PRECISION: specifies the precision at which a database records timestamps. Enter ms for milliseconds, us for microseconds, or ns for nanoseconds. The default value is ms.
|
||||
|
|
|
@ -24,7 +24,7 @@ SELECT [hints] [DISTINCT] select_list
|
|||
hints: /*+ [hint([hint_param_list])] [hint([hint_param_list])] */
|
||||
|
||||
hint:
|
||||
BATCH_SCAN | NO_BATCH_SCAN
|
||||
BATCH_SCAN | NO_BATCH_SCAN | SORT_FOR_GROUP
|
||||
|
||||
select_list:
|
||||
select_expr [, select_expr] ...
|
||||
|
@ -87,15 +87,17 @@ Hints are a means of user control over query optimization for individual stateme
|
|||
|
||||
The list of currently supported Hints is as follows:
|
||||
|
||||
| **Hint** | **Params** | **Comment** | **Scopt** |
|
||||
| :-----------: | -------------- | -------------------------- | -------------------------- |
|
||||
| BATCH_SCAN | None | Batch table scan | JOIN statment for stable |
|
||||
| NO_BATCH_SCAN | None | Sequential table scan | JOIN statment for stable |
|
||||
| **Hint** | **Params** | **Comment** | **Scopt** |
|
||||
| :-----------: | -------------- | -------------------------- | -----------------------------------|
|
||||
| BATCH_SCAN | None | Batch table scan | JOIN statment for stable |
|
||||
| NO_BATCH_SCAN | None | Sequential table scan | JOIN statment for stable |
|
||||
| SORT_FOR_GROUP| None | Use sort for partition | With normal column in partition by list |
|
||||
|
||||
For example:
|
||||
|
||||
```sql
|
||||
SELECT /*+ BATCH_SCAN() */ a.ts FROM stable1 a, stable2 b where a.tag0 = b.tag0 and a.ts = b.ts;
|
||||
SELECT /*+ SORT_FOR_GROUP() */ count(*), c1 FROM stable1 PARTITION BY c1;
|
||||
```
|
||||
|
||||
## Lists
|
||||
|
|
|
@ -54,6 +54,7 @@ LIKE is used together with wildcards to match strings. Its usage is described as
|
|||
MATCH and NMATCH are used together with regular expressions to match strings. Their usage is described as follows:
|
||||
|
||||
- Use POSIX regular expression syntax. For more information, see Regular Expressions.
|
||||
- The `MATCH` operator returns true when the regular expression is matched. The `NMATCH` operator returns true when the regular expression is not matched.
|
||||
- Regular expression can be used against only table names, i.e. `tbname`, and tags/columns of binary/nchar types.
|
||||
- The maximum length of regular expression string is 128 bytes. Configuration parameter `maxRegexStringLen` can be used to set the maximum allowed regular expression. It's a configuration parameter on the client side, and will take effect after restarting the client.
|
||||
|
||||
|
|
|
@ -73,10 +73,10 @@ Shows the SQL statement used to create the specified table. This statement can b
|
|||
## SHOW DATABASES
|
||||
|
||||
```sql
|
||||
SHOW DATABASES;
|
||||
SHOW [USER | SYSTEM] DATABASES;
|
||||
```
|
||||
|
||||
Shows all user-created databases.
|
||||
Shows all databases. The `USER` qualifier specifies only user-created databases. The `SYSTEM` qualifier specifies only system databases.
|
||||
|
||||
## SHOW DNODES
|
||||
|
||||
|
@ -183,10 +183,10 @@ Shows all subscriptions in the system.
|
|||
## SHOW TABLES
|
||||
|
||||
```sql
|
||||
SHOW [db_name.]TABLES [LIKE 'pattern'];
|
||||
SHOW [NORMAL | CHILD] [db_name.]TABLES [LIKE 'pattern'];
|
||||
```
|
||||
|
||||
Shows all standard tables and subtables in the current database. You can use LIKE for fuzzy matching.
|
||||
Shows all standard tables and subtables in the current database. You can use LIKE for fuzzy matching. The `Normal` qualifier specifies standard tables. The `CHILD` qualifier specifies subtables.
|
||||
|
||||
## SHOW TABLE DISTRIBUTED
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ database_option: {
|
|||
- WAL_FSYNC_PERIOD:当 WAL 参数设置为 2 时,落盘的周期。默认为 3000,单位毫秒。最小为 0,表示每次写入立即落盘;最大为 180000,即三分钟。
|
||||
- MAXROWS:文件块中记录的最大条数,默认为 4096 条。
|
||||
- MINROWS:文件块中记录的最小条数,默认为 100 条。
|
||||
- KEEP:表示数据文件保存的天数,缺省值为 3650,取值范围 [1, 365000],且必须大于或等于 DURATION 参数值。数据库会自动删除保存时间超过 KEEP 值的数据。KEEP 可以使用加单位的表示形式,如 KEEP 100h、KEEP 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。也可以不写单位,如 KEEP 50,此时默认单位为天。企业版支持[多级存储](https://docs.taosdata.com/tdinternal/arch/#%E5%A4%9A%E7%BA%A7%E5%AD%98%E5%82%A8)功能, 因此, 可以设置多个保存时间(多个以英文逗号分隔,最多 3 个,满足 keep 0 <= keep 1 <= keep 2,如 KEEP 100h,100d,3650d); 社区版不支持多级存储功能(即使配置了多个保存时间, 也不会生效, KEEP 会取最大的保存时间)。
|
||||
- KEEP:表示数据文件保存的天数,缺省值为 3650,取值范围 [1, 365000],且必须大于或等于3倍的 DURATION 参数值。数据库会自动删除保存时间超过 KEEP 值的数据。KEEP 可以使用加单位的表示形式,如 KEEP 100h、KEEP 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。也可以不写单位,如 KEEP 50,此时默认单位为天。企业版支持[多级存储](https://docs.taosdata.com/tdinternal/arch/#%E5%A4%9A%E7%BA%A7%E5%AD%98%E5%82%A8)功能, 因此, 可以设置多个保存时间(多个以英文逗号分隔,最多 3 个,满足 keep 0 <= keep 1 <= keep 2,如 KEEP 100h,100d,3650d); 社区版不支持多级存储功能(即使配置了多个保存时间, 也不会生效, KEEP 会取最大的保存时间)。
|
||||
- PAGES:一个 VNODE 中元数据存储引擎的缓存页个数,默认为 256,最小 64。一个 VNODE 元数据存储占用 PAGESIZE \* PAGES,默认情况下为 1MB 内存。
|
||||
- PAGESIZE:一个 VNODE 中元数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB 到 16 MB。
|
||||
- PRECISION:数据库的时间戳精度。ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认 ms 毫秒。
|
||||
|
|
|
@ -24,7 +24,7 @@ SELECT [hints] [DISTINCT] select_list
|
|||
hints: /*+ [hint([hint_param_list])] [hint([hint_param_list])] */
|
||||
|
||||
hint:
|
||||
BATCH_SCAN | NO_BATCH_SCAN
|
||||
BATCH_SCAN | NO_BATCH_SCAN | SORT_FOR_GROUP
|
||||
|
||||
select_list:
|
||||
select_expr [, select_expr] ...
|
||||
|
@ -87,15 +87,17 @@ Hints 是用户控制单个语句查询优化的一种手段,当 Hint 不适
|
|||
|
||||
目前支持的 Hints 列表如下:
|
||||
|
||||
| **Hint** | **参数** | **说明** | **适用范围** |
|
||||
| :-----------: | -------------- | -------------------------- | -------------------------- |
|
||||
| BATCH_SCAN | 无 | 采用批量读表的方式 | 超级表 JOIN 语句 |
|
||||
| NO_BATCH_SCAN | 无 | 采用顺序读表的方式 | 超级表 JOIN 语句 |
|
||||
| **Hint** | **参数** | **说明** | **适用范围** |
|
||||
| :-----------: | -------------- | -------------------------- | -----------------------------|
|
||||
| BATCH_SCAN | 无 | 采用批量读表的方式 | 超级表 JOIN 语句 |
|
||||
| NO_BATCH_SCAN | 无 | 采用顺序读表的方式 | 超级表 JOIN 语句 |
|
||||
| SORT_FOR_GROUP| 无 | 采用sort方式进行分组 | partition by 列表有普通列时 |
|
||||
|
||||
举例:
|
||||
|
||||
```sql
|
||||
SELECT /*+ BATCH_SCAN() */ a.ts FROM stable1 a, stable2 b where a.tag0 = b.tag0 and a.ts = b.ts;
|
||||
SELECT /*+ SORT_FOR_GROUP() */ count(*), c1 FROM stable1 PARTITION BY c1;
|
||||
```
|
||||
|
||||
## 列表
|
||||
|
|
|
@ -54,6 +54,7 @@ LIKE 条件使用通配符字符串进行匹配检查,规则如下:
|
|||
MATCH 条件和 NMATCH 条件使用正则表达式进行匹配,规则如下:
|
||||
|
||||
- 支持符合 POSIX 规范的正则表达式,具体规范内容可参见 Regular Expressions。
|
||||
- MATCH 和正则表达式匹配时, 返回 TURE. NMATCH 和正则表达式不匹配时, 返回 TRUE.
|
||||
- 只能针对子表名(即 tbname)、字符串类型的标签值进行正则表达式过滤,不支持普通列的过滤。
|
||||
- 正则匹配字符串长度不能超过 128 字节。可以通过参数 maxRegexStringLen 设置和调整最大允许的正则匹配字符串,该参数是客户端配置参数,需要重启客户端才能生效
|
||||
|
||||
|
|
|
@ -73,10 +73,10 @@ SHOW CREATE TABLE [db_name.]tb_name
|
|||
## SHOW DATABASES
|
||||
|
||||
```sql
|
||||
SHOW DATABASES;
|
||||
SHOW [USER | SYSTEM] DATABASES;
|
||||
```
|
||||
|
||||
显示用户定义的所有数据库。
|
||||
显示定义的所有数据库。SYSTEM 指定只显示系统数据库。USER 指定只显示用户创建的数据库。
|
||||
|
||||
## SHOW DNODES
|
||||
|
||||
|
@ -183,10 +183,10 @@ SHOW SUBSCRIPTIONS;
|
|||
## SHOW TABLES
|
||||
|
||||
```sql
|
||||
SHOW [db_name.]TABLES [LIKE 'pattern'];
|
||||
SHOW [NORMAL | CHILD] [db_name.]TABLES [LIKE 'pattern'];
|
||||
```
|
||||
|
||||
显示当前数据库下的所有普通表和子表的信息。可以使用 LIKE 对表名进行模糊匹配。
|
||||
显示当前数据库下的所有普通表和子表的信息。可以使用 LIKE 对表名进行模糊匹配。NORMAL 指定只显示普通表信息, CHILD 指定只显示子表信息。
|
||||
|
||||
## SHOW TABLE DISTRIBUTED
|
||||
|
||||
|
|
|
@ -51,8 +51,10 @@ typedef enum {
|
|||
} EGrantType;
|
||||
|
||||
int32_t grantCheck(EGrantType grant);
|
||||
#ifdef TD_ENTERPRISE
|
||||
#ifndef TD_GRANT_OPTIMIZE
|
||||
int32_t grantAlterActiveCode(const char* old, const char* new, char* out, int8_t type);
|
||||
#else
|
||||
int32_t grantAlterActiveCode(int32_t did, const char* old, const char* new, char* out, int8_t type);
|
||||
#endif
|
||||
|
||||
#ifndef GRANTS_CFG
|
||||
|
|
|
@ -2048,6 +2048,7 @@ int32_t tDeserializeSRedistributeVgroupReq(void* buf, int32_t bufLen, SRedistrib
|
|||
|
||||
typedef struct {
|
||||
int32_t useless;
|
||||
int32_t vgId;
|
||||
} SBalanceVgroupLeaderReq;
|
||||
|
||||
int32_t tSerializeSBalanceVgroupLeaderReq(void* buf, int32_t bufLen, SBalanceVgroupLeaderReq* pReq);
|
||||
|
|
|
@ -362,6 +362,8 @@
|
|||
#define TK_WAL 343
|
||||
|
||||
|
||||
|
||||
|
||||
#define TK_NK_SPACE 600
|
||||
#define TK_NK_COMMENT 601
|
||||
#define TK_NK_ILLEGAL 602
|
||||
|
|
|
@ -38,6 +38,9 @@ extern "C" {
|
|||
|
||||
#define META_READER_NOLOCK 0x1
|
||||
|
||||
#define STREAM_STATE_BUFF_HASH 1
|
||||
#define STREAM_STATE_BUFF_SORT 2
|
||||
|
||||
typedef struct SMeta SMeta;
|
||||
typedef TSKEY (*GetTsFun)(void*);
|
||||
|
||||
|
@ -115,6 +118,7 @@ typedef struct SRowBuffPos {
|
|||
void* pKey;
|
||||
bool beFlushed;
|
||||
bool beUsed;
|
||||
bool needFree;
|
||||
} SRowBuffPos;
|
||||
|
||||
// tq
|
||||
|
@ -333,6 +337,8 @@ typedef struct {
|
|||
void* db; // rocksdb_t* db;
|
||||
void* pCur;
|
||||
int64_t number;
|
||||
void* pStreamFileState;
|
||||
int32_t buffIndex;
|
||||
} SStreamStateCur;
|
||||
|
||||
typedef struct SStateStore {
|
||||
|
@ -340,7 +346,8 @@ typedef struct SStateStore {
|
|||
int32_t (*streamStateGetParName)(SStreamState* pState, int64_t groupId, void** pVal);
|
||||
|
||||
int32_t (*streamStateAddIfNotExist)(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateReleaseBuf)(SStreamState* pState, const SWinKey* key, void* pVal);
|
||||
int32_t (*streamStateReleaseBuf)(SStreamState* pState, void* pVal, bool used);
|
||||
int32_t (*streamStateClearBuff)(SStreamState* pState, void* pVal);
|
||||
void (*streamStateFreeVal)(void* val);
|
||||
|
||||
int32_t (*streamStatePut)(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen);
|
||||
|
@ -371,7 +378,7 @@ typedef struct SStateStore {
|
|||
|
||||
int32_t (*streamStateSessionAddIfNotExist)(SStreamState* pState, SSessionKey* key, TSKEY gap, void** pVal,
|
||||
int32_t* pVLen);
|
||||
int32_t (*streamStateSessionPut)(SStreamState* pState, const SSessionKey* key, const void* value, int32_t vLen);
|
||||
int32_t (*streamStateSessionPut)(SStreamState* pState, const SSessionKey* key, void* value, int32_t vLen);
|
||||
int32_t (*streamStateSessionGet)(SStreamState* pState, SSessionKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateSessionDel)(SStreamState* pState, const SSessionKey* key);
|
||||
int32_t (*streamStateSessionClear)(SStreamState* pState);
|
||||
|
@ -400,7 +407,7 @@ typedef struct SStateStore {
|
|||
|
||||
struct SStreamFileState* (*streamFileStateInit)(int64_t memSize, uint32_t keySize, uint32_t rowSize,
|
||||
uint32_t selectRowSize, GetTsFun fp, void* pFile, TSKEY delMark,
|
||||
const char* id, int64_t ckId);
|
||||
const char* id, int64_t ckId, int8_t type);
|
||||
|
||||
void (*streamFileStateDestroy)(struct SStreamFileState* pFileState);
|
||||
void (*streamFileStateClear)(struct SStreamFileState* pFileState);
|
||||
|
|
|
@ -507,6 +507,7 @@ typedef struct SBalanceVgroupStmt {
|
|||
|
||||
typedef struct SBalanceVgroupLeaderStmt {
|
||||
ENodeType type;
|
||||
int32_t vgId;
|
||||
} SBalanceVgroupLeaderStmt;
|
||||
|
||||
typedef struct SMergeVgroupStmt {
|
||||
|
|
|
@ -49,26 +49,30 @@ void streamStateSetNumber(SStreamState* pState, int32_t number);
|
|||
int32_t streamStateSaveInfo(SStreamState* pState, void* pKey, int32_t keyLen, void* pVal, int32_t vLen);
|
||||
int32_t streamStateGetInfo(SStreamState* pState, void* pKey, int32_t keyLen, void** pVal, int32_t* pLen);
|
||||
|
||||
//session window
|
||||
int32_t streamStateSessionAddIfNotExist(SStreamState* pState, SSessionKey* key, TSKEY gap, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateSessionPut(SStreamState* pState, const SSessionKey* key, const void* value, int32_t vLen);
|
||||
int32_t streamStateSessionPut(SStreamState* pState, const SSessionKey* key, void* value, int32_t vLen);
|
||||
int32_t streamStateSessionGet(SStreamState* pState, SSessionKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateSessionDel(SStreamState* pState, const SSessionKey* key);
|
||||
int32_t streamStateSessionClear(SStreamState* pState);
|
||||
int32_t streamStateSessionGetKVByCur(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateStateAddIfNotExist(SStreamState* pState, SSessionKey* key, char* pKeyData, int32_t keyDataLen,
|
||||
state_key_cmpr_fn fn, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateSessionGetKeyByRange(SStreamState* pState, const SSessionKey* range, SSessionKey* curKey);
|
||||
|
||||
SStreamStateCur* streamStateSessionSeekKeyNext(SStreamState* pState, const SSessionKey* key);
|
||||
SStreamStateCur* streamStateSessionSeekKeyCurrentPrev(SStreamState* pState, const SSessionKey* key);
|
||||
SStreamStateCur* streamStateSessionSeekKeyCurrentNext(SStreamState* pState, const SSessionKey* key);
|
||||
|
||||
//state window
|
||||
int32_t streamStateStateAddIfNotExist(SStreamState* pState, SSessionKey* key, char* pKeyData, int32_t keyDataLen,
|
||||
state_key_cmpr_fn fn, void** pVal, int32_t* pVLen);
|
||||
|
||||
int32_t streamStateFillPut(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen);
|
||||
int32_t streamStateFillGet(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateFillDel(SStreamState* pState, const SWinKey* key);
|
||||
|
||||
int32_t streamStateAddIfNotExist(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateReleaseBuf(SStreamState* pState, const SWinKey* key, void* pVal);
|
||||
int32_t streamStateReleaseBuf(SStreamState* pState, void* pVal, bool used);
|
||||
int32_t streamStateClearBuff(SStreamState* pState, void* pVal);
|
||||
void streamStateFreeVal(void* val);
|
||||
|
||||
SStreamStateCur* streamStateGetAndCheckCur(SStreamState* pState, SWinKey* key);
|
||||
|
@ -76,14 +80,11 @@ SStreamStateCur* streamStateSeekKeyNext(SStreamState* pState, const SWinKey* key
|
|||
SStreamStateCur* streamStateFillSeekKeyNext(SStreamState* pState, const SWinKey* key);
|
||||
SStreamStateCur* streamStateFillSeekKeyPrev(SStreamState* pState, const SWinKey* key);
|
||||
void streamStateFreeCur(SStreamStateCur* pCur);
|
||||
void streamStateResetCur(SStreamStateCur* pCur);
|
||||
|
||||
int32_t streamStateGetGroupKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateGetKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
|
||||
int32_t streamStateGetFirst(SStreamState* pState, SWinKey* key);
|
||||
int32_t streamStateSeekFirst(SStreamState* pState, SStreamStateCur* pCur);
|
||||
int32_t streamStateSeekLast(SStreamState* pState, SStreamStateCur* pCur);
|
||||
|
||||
int32_t streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur);
|
||||
int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur);
|
||||
|
||||
|
@ -91,6 +92,7 @@ int32_t streamStatePutParName(SStreamState* pState, int64_t groupId, const char*
|
|||
int32_t streamStateGetParName(SStreamState* pState, int64_t groupId, void** pVal);
|
||||
|
||||
void streamStateReloadInfo(SStreamState* pState, TSKEY ts);
|
||||
SStreamStateCur* createStreamStateCursor();
|
||||
|
||||
/***compare func **/
|
||||
|
||||
|
|
|
@ -28,20 +28,33 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct SStreamFileState SStreamFileState;
|
||||
typedef SList SStreamSnapshot;
|
||||
typedef SList SStreamSnapshot;
|
||||
|
||||
typedef void* (*_state_buff_get_fn)(void* pRowBuff, const void* pKey, size_t keyLen);
|
||||
typedef int32_t (*_state_buff_put_fn)(void* pRowBuff, const void* pKey, size_t keyLen, const void* data, size_t dataLen);
|
||||
typedef int32_t (*_state_buff_remove_fn)(void* pRowBuff, const void* pKey, size_t keyLen);
|
||||
typedef int32_t (*_state_buff_remove_by_pos_fn)(SStreamFileState* pState, SRowBuffPos* pPos);
|
||||
typedef void (*_state_buff_cleanup_fn)(void* pRowBuff);
|
||||
typedef void* (*_state_buff_create_statekey_fn)(SRowBuffPos* pPos, int64_t num);
|
||||
|
||||
typedef int32_t (*_state_file_remove_fn)(SStreamFileState* pFileState, const void* pKey);
|
||||
typedef int32_t (*_state_file_get_fn)(SStreamFileState* pFileState, void* pKey, void* data, int32_t* pDataLen);
|
||||
typedef int32_t (*_state_file_clear_fn)(SStreamState* pState);
|
||||
|
||||
SStreamFileState* streamFileStateInit(int64_t memSize, uint32_t keySize, uint32_t rowSize, uint32_t selectRowSize,
|
||||
GetTsFun fp, void* pFile, TSKEY delMark, const char* taskId,
|
||||
int64_t checkpointId);
|
||||
int64_t checkpointId, int8_t type);
|
||||
void streamFileStateDestroy(SStreamFileState* pFileState);
|
||||
void streamFileStateClear(SStreamFileState* pFileState);
|
||||
bool needClearDiskBuff(SStreamFileState* pFileState);
|
||||
void streamFileStateReleaseBuff(SStreamFileState* pFileState, SRowBuffPos* pPos, bool used);
|
||||
int32_t streamFileStateClearBuff(SStreamFileState* pFileState, SRowBuffPos* pPos);
|
||||
|
||||
int32_t getRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen, void** pVal, int32_t* pVLen);
|
||||
int32_t deleteRowBuff(SStreamFileState* pFileState, const void* pKey, int32_t keyLen);
|
||||
int32_t getRowBuffByPos(SStreamFileState* pFileState, SRowBuffPos* pPos, void** pVal);
|
||||
void releaseRowBuffPos(SRowBuffPos* pBuff);
|
||||
bool hasRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen);
|
||||
void putFreeBuff(SStreamFileState* pFileState, SRowBuffPos* pPos);
|
||||
|
||||
SStreamSnapshot* getSnapshot(SStreamFileState* pFileState);
|
||||
int32_t flushSnapshot(SStreamFileState* pFileState, SStreamSnapshot* pSnapshot, bool flushState);
|
||||
|
@ -52,6 +65,34 @@ int32_t deleteExpiredCheckPoint(SStreamFileState* pFileState, TSKEY mark);
|
|||
int32_t streamFileStateGeSelectRowSize(SStreamFileState* pFileState);
|
||||
void streamFileStateReloadInfo(SStreamFileState* pFileState, TSKEY ts);
|
||||
|
||||
void* getRowStateBuff(SStreamFileState* pFileState);
|
||||
void* getStateFileStore(SStreamFileState* pFileState);
|
||||
bool isDeteled(SStreamFileState* pFileState, TSKEY ts);
|
||||
bool isFlushedState(SStreamFileState* pFileState, TSKEY ts, TSKEY gap);
|
||||
SRowBuffPos* getNewRowPosForWrite(SStreamFileState* pFileState);
|
||||
int32_t getRowStateRowSize(SStreamFileState* pFileState);
|
||||
|
||||
// session window
|
||||
int32_t getSessionWinResultBuff(SStreamFileState* pFileState, SSessionKey* pKey, TSKEY gap, void** pVal, int32_t* pVLen);
|
||||
int32_t putSessionWinResultBuff(SStreamFileState* pFileState, SRowBuffPos* pPos);
|
||||
int32_t getSessionFlushedBuff(SStreamFileState* pFileState, SSessionKey* pKey, void** pVal, int32_t* pVLen);
|
||||
int32_t deleteSessionWinStateBuffFn(void* pBuff, const void *key, size_t keyLen);
|
||||
int32_t deleteSessionWinStateBuffByPosFn(SStreamFileState* pFileState, SRowBuffPos* pPos);
|
||||
|
||||
void sessionWinStateClear(SStreamFileState* pFileState);
|
||||
void sessionWinStateCleanup(void* pBuff);
|
||||
|
||||
SStreamStateCur* sessionWinStateSeekKeyCurrentPrev(SStreamFileState* pFileState, const SSessionKey* pWinKey);
|
||||
SStreamStateCur* sessionWinStateSeekKeyCurrentNext(SStreamFileState* pFileState, const SSessionKey* pWinKey);
|
||||
SStreamStateCur* sessionWinStateSeekKeyNext(SStreamFileState* pFileState, const SSessionKey* pWinKey);
|
||||
int32_t sessionWinStateGetKVByCur(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen);
|
||||
int32_t sessionWinStateMoveToNext(SStreamStateCur* pCur);
|
||||
int32_t sessionWinStateGetKeyByRange(SStreamFileState* pFileState, const SSessionKey* key, SSessionKey* curKey);
|
||||
|
||||
// state window
|
||||
int32_t getStateWinResultBuff(SStreamFileState* pFileState, SSessionKey* key, char* pKeyData, int32_t keyDataLen,
|
||||
state_key_cmpr_fn fn, void** pVal, int32_t* pVLen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -382,6 +382,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_MAX_STT_TRIGGER 1
|
||||
#define TSDB_DEFAULT_SST_TRIGGER 1
|
||||
#endif
|
||||
#define TSDB_STT_TRIGGER_ARRAY_SIZE 16 // maximum of TSDB_MAX_STT_TRIGGER of TD_ENTERPRISE and TD_COMMUNITY
|
||||
#define TSDB_MIN_HASH_PREFIX (2 - TSDB_TABLE_NAME_LEN)
|
||||
#define TSDB_MAX_HASH_PREFIX (TSDB_TABLE_NAME_LEN - 2)
|
||||
#define TSDB_DEFAULT_HASH_PREFIX 0
|
||||
|
|
|
@ -157,6 +157,10 @@ STscObj* taos_connect_internal(const char* ip, const char* user, const char* pas
|
|||
tscDebug("new app inst mgr %p, user:%s, ip:%s, port:%d", p, user, epSet.epSet.eps[0].fqdn, epSet.epSet.eps[0].port);
|
||||
|
||||
pInst = &p;
|
||||
} else {
|
||||
ASSERTS((*pInst) && (*pInst)->pAppHbMgr, "*pInst:%p, pAppHgMgr:%p", *pInst, (*pInst) ? (*pInst)->pAppHbMgr : NULL);
|
||||
// reset to 0 in case of conn with duplicated user key but its user has ever been dropped.
|
||||
atomic_store_8(&(*pInst)->pAppHbMgr->connHbFlag, 0);
|
||||
}
|
||||
|
||||
taosThreadMutexUnlock(&appInfo.mutex);
|
||||
|
|
|
@ -5240,6 +5240,7 @@ int32_t tSerializeSBalanceVgroupLeaderReq(void *buf, int32_t bufLen, SBalanceVgr
|
|||
|
||||
if (tStartEncode(&encoder) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pReq->useless) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pReq->vgId) < 0) return -1;
|
||||
tEndEncode(&encoder);
|
||||
|
||||
int32_t tlen = encoder.pos;
|
||||
|
@ -5253,6 +5254,9 @@ int32_t tDeserializeSBalanceVgroupLeaderReq(void *buf, int32_t bufLen, SBalanceV
|
|||
|
||||
if (tStartDecode(&decoder) < 0) return -1;
|
||||
if (tDecodeI32(&decoder, &pReq->useless) < 0) return -1;
|
||||
if(!tDecodeIsEnd(&decoder)){
|
||||
if (tDecodeI32(&decoder, &pReq->vgId) < 0) return -1;
|
||||
}
|
||||
tEndDecode(&decoder);
|
||||
|
||||
tDecoderClear(&decoder);
|
||||
|
|
|
@ -21,7 +21,7 @@ static int32_t dmStartMgmt(SDnodeMgmt *pMgmt) {
|
|||
if (dmStartStatusThread(pMgmt) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#if defined(TD_ENTERPRISE) && !defined(_TD_DARWIN_64)
|
||||
#if defined(TD_ENTERPRISE)
|
||||
if (dmStartNotifyThread(pMgmt) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -39,7 +39,9 @@ static void dmStopMgmt(SDnodeMgmt *pMgmt) {
|
|||
pMgmt->pData->stopped = true;
|
||||
dmStopMonitorThread(pMgmt);
|
||||
dmStopStatusThread(pMgmt);
|
||||
#if defined(TD_ENTERPRISE)
|
||||
dmStopNotifyThread(pMgmt);
|
||||
#endif
|
||||
dmStopCrashReportThread(pMgmt);
|
||||
}
|
||||
|
||||
|
|
|
@ -720,8 +720,8 @@ static int32_t mndProcessNotifyReq(SRpcMsg *pReq) {
|
|||
mndReleaseVgroup(pMnode, pVgroup);
|
||||
}
|
||||
}
|
||||
mndUpdClusterInfo(pReq);
|
||||
_OVER:
|
||||
mndUpdClusterInfo(pReq);
|
||||
tFreeSNotifyReq(¬ifyReq);
|
||||
return code;
|
||||
}
|
||||
|
@ -781,10 +781,11 @@ static int32_t mndConfigDnode(SMnode *pMnode, SRpcMsg *pReq, SMCfgDnodeReq *pCfg
|
|||
|
||||
SDnodeObj tmpDnode = *pDnode;
|
||||
if (action == DND_ACTIVE_CODE) {
|
||||
#ifndef TD_CHECK_ACTIVE
|
||||
strncpy(tmpDnode.active, pCfgReq->value, TSDB_ACTIVE_KEY_LEN);
|
||||
#else
|
||||
#ifndef TD_GRANT_OPTIMIZE
|
||||
if (grantAlterActiveCode(pDnode->active, pCfgReq->value, tmpDnode.active, 0) != 0) {
|
||||
#else
|
||||
if (grantAlterActiveCode(pDnode->id, pDnode->active, pCfgReq->value, tmpDnode.active, 0) != 0) {
|
||||
#endif
|
||||
if (TSDB_CODE_DUP_KEY != terrno) {
|
||||
mError("dnode:%d, config dnode:%d, app:%p config:%s value:%s failed since %s", pDnode->id, pCfgReq->dnodeId,
|
||||
pReq->info.ahandle, pCfgReq->config, pCfgReq->value, terrstr());
|
||||
|
@ -799,12 +800,12 @@ static int32_t mndConfigDnode(SMnode *pMnode, SRpcMsg *pReq, SMCfgDnodeReq *pCfg
|
|||
if (cfgAll) continue;
|
||||
goto _OVER;
|
||||
}
|
||||
#endif
|
||||
} else if (action == DND_CONN_ACTIVE_CODE) {
|
||||
#ifndef TD_CHECK_ACTIVE
|
||||
strncpy(tmpDnode.connActive, pCfgReq->value, TSDB_CONN_ACTIVE_KEY_LEN);
|
||||
#else
|
||||
#ifndef TD_GRANT_OPTIMIZE
|
||||
if (grantAlterActiveCode(pDnode->connActive, pCfgReq->value, tmpDnode.connActive, 1) != 0) {
|
||||
#else
|
||||
if (grantAlterActiveCode(pDnode->id, pDnode->connActive, pCfgReq->value, tmpDnode.connActive, 1) != 0) {
|
||||
#endif
|
||||
if (TSDB_CODE_DUP_KEY != terrno) {
|
||||
mError("dnode:%d, config dnode:%d, app:%p config:%s value:%s failed since %s", pDnode->id, pCfgReq->dnodeId,
|
||||
pReq->info.ahandle, pCfgReq->config, pCfgReq->value, terrstr());
|
||||
|
@ -819,7 +820,6 @@ static int32_t mndConfigDnode(SMnode *pMnode, SRpcMsg *pReq, SMCfgDnodeReq *pCfg
|
|||
if (cfgAll) continue;
|
||||
goto _OVER;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
terrno = TSDB_CODE_INVALID_CFG;
|
||||
goto _OVER;
|
||||
|
|
|
@ -131,6 +131,13 @@ void grantAdd(EGrantType grant, uint64_t value) {}
|
|||
void grantRestore(EGrantType grant, uint64_t value) {}
|
||||
int32_t dmProcessGrantReq(void *pInfo, SRpcMsg *pMsg) { return TSDB_CODE_SUCCESS; }
|
||||
int32_t dmProcessGrantNotify(void *pInfo, SRpcMsg *pMsg) { return TSDB_CODE_SUCCESS; }
|
||||
#ifndef TD_GRANT_OPTIMIZE
|
||||
int32_t grantAlterActiveCode(const char *old, const char *new, char *out, int8_t type) { return TSDB_CODE_SUCCESS; }
|
||||
#else
|
||||
int32_t grantAlterActiveCode(int32_t did, const char *old, const char *new, char *out, int8_t type) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -543,6 +543,10 @@ STrans *mndAcquireTrans(SMnode *pMnode, int32_t transId) {
|
|||
STrans *pTrans = sdbAcquire(pMnode->pSdb, SDB_TRANS, &transId);
|
||||
if (pTrans == NULL) {
|
||||
terrno = TSDB_CODE_MND_TRANS_NOT_EXIST;
|
||||
} else {
|
||||
#ifdef WINDOWS
|
||||
taosThreadMutexInit(&pTrans->mutex, NULL);
|
||||
#endif
|
||||
}
|
||||
return pTrans;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,12 @@ void initStateStoreAPI(SStateStore* pStore) {
|
|||
pStore->streamFileStateInit = streamFileStateInit;
|
||||
pStore->updateInfoDestoryColseWinSBF = updateInfoDestoryColseWinSBF;
|
||||
|
||||
pStore->streamStateGetByPos = streamStateGetByPos;
|
||||
|
||||
pStore->streamStatePutParName = streamStatePutParName;
|
||||
pStore->streamStateGetParName = streamStateGetParName;
|
||||
|
||||
pStore->streamStateAddIfNotExist = streamStateAddIfNotExist;
|
||||
pStore->streamStateReleaseBuf = streamStateReleaseBuf;
|
||||
pStore->streamStateClearBuff = streamStateClearBuff;
|
||||
pStore->streamStateFreeVal = streamStateFreeVal;
|
||||
|
||||
pStore->streamStatePut = streamStatePut;
|
||||
|
@ -91,8 +90,6 @@ void initStateStoreAPI(SStateStore* pStore) {
|
|||
pStore->streamStateSessionSeekKeyCurrentPrev = streamStateSessionSeekKeyCurrentPrev;
|
||||
pStore->streamStateSessionSeekKeyCurrentNext = streamStateSessionSeekKeyCurrentNext;
|
||||
|
||||
pStore->streamFileStateInit = streamFileStateInit;
|
||||
|
||||
pStore->streamFileStateDestroy = streamFileStateDestroy;
|
||||
pStore->streamFileStateClear = streamFileStateClear;
|
||||
pStore->needClearDiskBuff = needClearDiskBuff;
|
||||
|
|
|
@ -625,7 +625,7 @@ struct SDFileSet {
|
|||
SDataFile *pDataF;
|
||||
SSmaFile *pSmaF;
|
||||
uint8_t nSttF;
|
||||
SSttFile *aSttF[TSDB_MAX_STT_TRIGGER];
|
||||
SSttFile *aSttF[TSDB_STT_TRIGGER_ARRAY_SIZE];
|
||||
};
|
||||
|
||||
struct STSDBRowIter {
|
||||
|
@ -694,7 +694,7 @@ struct SDataFWriter {
|
|||
SHeadFile fHead;
|
||||
SDataFile fData;
|
||||
SSmaFile fSma;
|
||||
SSttFile fStt[TSDB_MAX_STT_TRIGGER];
|
||||
SSttFile fStt[TSDB_STT_TRIGGER_ARRAY_SIZE];
|
||||
|
||||
uint8_t *aBuf[4];
|
||||
};
|
||||
|
@ -705,7 +705,7 @@ struct SDataFReader {
|
|||
STsdbFD *pHeadFD;
|
||||
STsdbFD *pDataFD;
|
||||
STsdbFD *pSmaFD;
|
||||
STsdbFD *aSttFD[TSDB_MAX_STT_TRIGGER];
|
||||
STsdbFD *aSttFD[TSDB_STT_TRIGGER_ARRAY_SIZE];
|
||||
uint8_t *aBuf[3];
|
||||
};
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ int metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSche
|
|||
}
|
||||
|
||||
static inline void metaTimeSeriesNotifyCheck(SMeta *pMeta) {
|
||||
#if defined(TD_ENTERPRISE) && !defined(_TD_DARWIN_64)
|
||||
#if defined(TD_ENTERPRISE)
|
||||
int64_t nTimeSeries = metaGetTimeSeriesNum(pMeta, 0);
|
||||
int64_t deltaTS = nTimeSeries - pMeta->pVnode->config.vndStats.numOfReportedTimeSeries;
|
||||
if (deltaTS > tsTimeSeriesThreshold) {
|
||||
|
|
|
@ -69,7 +69,7 @@ typedef struct {
|
|||
SDataIter *pIter;
|
||||
SRBTree rbt;
|
||||
SDataIter dataIter;
|
||||
SDataIter aDataIter[TSDB_MAX_STT_TRIGGER];
|
||||
SDataIter aDataIter[TSDB_STT_TRIGGER_ARRAY_SIZE];
|
||||
int8_t toLastOnly;
|
||||
};
|
||||
struct {
|
||||
|
@ -865,7 +865,7 @@ static int32_t tsdbCommitDataStart(SCommitter *pCommitter) {
|
|||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
// merger
|
||||
for (int32_t iStt = 0; iStt < TSDB_MAX_STT_TRIGGER; iStt++) {
|
||||
for (int32_t iStt = 0; iStt < TSDB_STT_TRIGGER_ARRAY_SIZE; iStt++) {
|
||||
SDataIter *pIter = &pCommitter->aDataIter[iStt];
|
||||
pIter->aSttBlk = taosArrayInit(0, sizeof(SSttBlk));
|
||||
if (pIter->aSttBlk == NULL) {
|
||||
|
@ -915,7 +915,7 @@ static void tsdbCommitDataEnd(SCommitter *pCommitter) {
|
|||
tBlockDataDestroy(&pCommitter->dReader.bData);
|
||||
|
||||
// merger
|
||||
for (int32_t iStt = 0; iStt < TSDB_MAX_STT_TRIGGER; iStt++) {
|
||||
for (int32_t iStt = 0; iStt < TSDB_STT_TRIGGER_ARRAY_SIZE; iStt++) {
|
||||
SDataIter *pIter = &pCommitter->aDataIter[iStt];
|
||||
taosArrayDestroy(pIter->aSttBlk);
|
||||
tBlockDataDestroy(&pIter->bData);
|
||||
|
|
|
@ -1000,7 +1000,7 @@ int32_t tsdbDataFReaderClose(SDataFReader **ppReader) {
|
|||
tsdbCloseFile(&(*ppReader)->pSmaFD);
|
||||
|
||||
// stt
|
||||
for (int32_t iStt = 0; iStt < TSDB_MAX_STT_TRIGGER; iStt++) {
|
||||
for (int32_t iStt = 0; iStt < TSDB_STT_TRIGGER_ARRAY_SIZE; iStt++) {
|
||||
if ((*ppReader)->aSttFD[iStt]) {
|
||||
tsdbCloseFile(&(*ppReader)->aSttFD[iStt]);
|
||||
}
|
||||
|
|
|
@ -372,6 +372,14 @@ static int32_t tsdbDoRetention2(void *arg) {
|
|||
|
||||
_exit:
|
||||
if (code) {
|
||||
if (TARRAY2_DATA(rtner->fopArr)) {
|
||||
TARRAY2_DESTROY(rtner->fopArr, NULL);
|
||||
}
|
||||
TFileSetArray **fsetArr = &rtner->fsetArr;
|
||||
if (fsetArr[0]) {
|
||||
tsdbFSDestroyCopySnapshot(&rtner->fsetArr);
|
||||
}
|
||||
|
||||
TSDB_ERROR_LOG(TD_VID(rtner->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
|
|
|
@ -137,13 +137,12 @@ void initStateStoreAPI(SStateStore* pStore) {
|
|||
pStore->streamFileStateInit = streamFileStateInit;
|
||||
pStore->updateInfoDestoryColseWinSBF = updateInfoDestoryColseWinSBF;
|
||||
|
||||
pStore->streamStateGetByPos = streamStateGetByPos;
|
||||
|
||||
pStore->streamStatePutParName = streamStatePutParName;
|
||||
pStore->streamStateGetParName = streamStateGetParName;
|
||||
|
||||
pStore->streamStateAddIfNotExist = streamStateAddIfNotExist;
|
||||
pStore->streamStateReleaseBuf = streamStateReleaseBuf;
|
||||
pStore->streamStateClearBuff = streamStateClearBuff;
|
||||
pStore->streamStateFreeVal = streamStateFreeVal;
|
||||
|
||||
pStore->streamStatePut = streamStatePut;
|
||||
|
@ -199,8 +198,6 @@ void initStateStoreAPI(SStateStore* pStore) {
|
|||
pStore->streamStateSessionSeekKeyCurrentPrev = streamStateSessionSeekKeyCurrentPrev;
|
||||
pStore->streamStateSessionSeekKeyCurrentNext = streamStateSessionSeekKeyCurrentNext;
|
||||
|
||||
pStore->streamFileStateInit = streamFileStateInit;
|
||||
|
||||
pStore->streamFileStateDestroy = streamFileStateDestroy;
|
||||
pStore->streamFileStateClear = streamFileStateClear;
|
||||
pStore->needClearDiskBuff = needClearDiskBuff;
|
||||
|
|
|
@ -548,9 +548,9 @@ typedef struct SWindowRowsSup {
|
|||
} SWindowRowsSup;
|
||||
|
||||
typedef struct SResultWindowInfo {
|
||||
void* pOutputBuf;
|
||||
SSessionKey sessionWin;
|
||||
bool isOutput;
|
||||
SRowBuffPos* pStatePos;
|
||||
SSessionKey sessionWin;
|
||||
bool isOutput;
|
||||
} SResultWindowInfo;
|
||||
|
||||
typedef struct SStreamSessionAggOperatorInfo {
|
||||
|
@ -579,6 +579,7 @@ typedef struct SStreamSessionAggOperatorInfo {
|
|||
bool isHistoryOp;
|
||||
bool reCkBlock;
|
||||
SSDataBlock* pCheckpointRes;
|
||||
bool clearState;
|
||||
} SStreamSessionAggOperatorInfo;
|
||||
|
||||
typedef struct SStreamStateAggOperatorInfo {
|
||||
|
@ -672,8 +673,6 @@ void cleanupAggSup(SAggSupporter* pAggSup);
|
|||
|
||||
void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows);
|
||||
|
||||
void doBuildStreamResBlock(struct SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo,
|
||||
SDiskbasedBuf* pBuf);
|
||||
void doBuildResultDatablock(struct SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo,
|
||||
SDiskbasedBuf* pBuf);
|
||||
|
||||
|
@ -739,12 +738,6 @@ int32_t finalizeResultRows(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPos
|
|||
SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo);
|
||||
|
||||
bool groupbyTbname(SNodeList* pGroupList);
|
||||
int32_t buildDataBlockFromGroupRes(struct SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
|
||||
SGroupResInfo* pGroupResInfo);
|
||||
int32_t saveSessionDiscBuf(void* pState, SSessionKey* key, void* buf, int32_t size, SStateStore* pAPI);
|
||||
int32_t buildSessionResultDataBlock(struct SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
|
||||
SGroupResInfo* pGroupResInfo);
|
||||
int32_t releaseOutputBuf(void* pState, SWinKey* pKey, SResultRow* pResult, SStateStore* pAPI);
|
||||
void getNextIntervalWindow(SInterval* pInterval, STimeWindow* tw, int32_t order);
|
||||
int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int32_t pos, int32_t order,
|
||||
int64_t* pData);
|
||||
|
|
|
@ -720,38 +720,6 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprS
|
|||
return 0;
|
||||
}
|
||||
|
||||
void doBuildStreamResBlock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo,
|
||||
SDiskbasedBuf* pBuf) {
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SStorageAPI* pAPI = &pTaskInfo->storageAPI;
|
||||
|
||||
SSDataBlock* pBlock = pbInfo->pRes;
|
||||
|
||||
// set output datablock version
|
||||
pBlock->info.version = pTaskInfo->version;
|
||||
|
||||
blockDataCleanup(pBlock);
|
||||
if (!hasRemainResults(pGroupResInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the existed group id
|
||||
pBlock->info.id.groupId = 0;
|
||||
ASSERT(!pbInfo->mergeResultBlock);
|
||||
doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo, pOperator->resultInfo.threshold,
|
||||
false);
|
||||
|
||||
void* tbname = NULL;
|
||||
if (pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) <
|
||||
0) {
|
||||
pBlock->info.parTbName[0] = 0;
|
||||
} else {
|
||||
memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
|
||||
}
|
||||
|
||||
pAPI->stateStore.streamStateFreeVal(tbname);
|
||||
}
|
||||
|
||||
void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo,
|
||||
SDiskbasedBuf* pBuf) {
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
@ -960,109 +928,6 @@ int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, SExecTaskInfo*
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t releaseOutputBuf(void* pState, SWinKey* pKey, SResultRow* pResult, SStateStore* pAPI) {
|
||||
pAPI->streamStateReleaseBuf(pState, pKey, pResult);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t saveSessionDiscBuf(void* pState, SSessionKey* key, void* buf, int32_t size, SStateStore* pAPI) {
|
||||
pAPI->streamStateSessionPut(pState, key, (const void*)buf, size);
|
||||
releaseOutputBuf(pState, NULL, (SResultRow*)buf, pAPI);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
|
||||
SGroupResInfo* pGroupResInfo) {
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SStorageAPI* pAPI = &pTaskInfo->storageAPI;
|
||||
|
||||
SExprInfo* pExprInfo = pSup->pExprInfo;
|
||||
int32_t numOfExprs = pSup->numOfExprs;
|
||||
int32_t* rowEntryOffset = pSup->rowEntryInfoOffset;
|
||||
SqlFunctionCtx* pCtx = pSup->pCtx;
|
||||
|
||||
int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
|
||||
|
||||
for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
|
||||
SSessionKey* pKey = taosArrayGet(pGroupResInfo->pRows, i);
|
||||
int32_t size = 0;
|
||||
void* pVal = NULL;
|
||||
int32_t code = pAPI->stateStore.streamStateSessionGet(pState, pKey, &pVal, &size);
|
||||
// ASSERT(code == 0);
|
||||
if (code == -1) {
|
||||
// for history
|
||||
qWarn("===stream===not found session result key:%" PRId64 ", ekey:%" PRId64 ", groupId:%" PRIu64 "",
|
||||
pKey->win.skey, pKey->win.ekey, pKey->groupId);
|
||||
pGroupResInfo->index += 1;
|
||||
continue;
|
||||
}
|
||||
SResultRow* pRow = (SResultRow*)pVal;
|
||||
doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
|
||||
// no results, continue to check the next one
|
||||
if (pRow->numOfRows == 0) {
|
||||
pGroupResInfo->index += 1;
|
||||
releaseOutputBuf(pState, NULL, pRow, &pAPI->stateStore);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pBlock->info.id.groupId == 0) {
|
||||
pBlock->info.id.groupId = pKey->groupId;
|
||||
|
||||
void* tbname = NULL;
|
||||
if (pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId,
|
||||
&tbname) < 0) {
|
||||
pBlock->info.parTbName[0] = 0;
|
||||
} else {
|
||||
memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
|
||||
}
|
||||
pAPI->stateStore.streamStateFreeVal(tbname);
|
||||
} else {
|
||||
// current value belongs to different group, it can't be packed into one datablock
|
||||
if (pBlock->info.id.groupId != pKey->groupId) {
|
||||
releaseOutputBuf(pState, NULL, pRow, &pAPI->stateStore);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
|
||||
ASSERT(pBlock->info.rows > 0);
|
||||
releaseOutputBuf(pState, NULL, pRow, &pAPI->stateStore);
|
||||
break;
|
||||
}
|
||||
|
||||
pGroupResInfo->index += 1;
|
||||
|
||||
for (int32_t j = 0; j < numOfExprs; ++j) {
|
||||
int32_t slotId = pExprInfo[j].base.resSchema.slotId;
|
||||
|
||||
pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
|
||||
if (pCtx[j].fpSet.finalize) {
|
||||
int32_t code1 = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
|
||||
if (TAOS_FAILED(code1)) {
|
||||
qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code1));
|
||||
T_LONG_JMP(pTaskInfo->env, code1);
|
||||
}
|
||||
} else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
|
||||
// do nothing, todo refactor
|
||||
} else {
|
||||
// expand the result into multiple rows. E.g., _wstart, top(k, 20)
|
||||
// the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
|
||||
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
|
||||
char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
|
||||
for (int32_t k = 0; k < pRow->numOfRows; ++k) {
|
||||
colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pBlock->info.dataLoad = 1;
|
||||
pBlock->info.rows += pRow->numOfRows;
|
||||
releaseOutputBuf(pState, NULL, pRow, &pAPI->stateStore);
|
||||
}
|
||||
blockDataUpdateTsWindow(pBlock, 0);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void streamOpReleaseState(SOperatorInfo* pOperator) {
|
||||
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||
if (downstream->fpSet.releaseStreamStateFn) {
|
||||
|
|
|
@ -1057,7 +1057,7 @@ void appendCreateTableRow(void* pState, SExprSupp* pTableSup, SExprSupp* pTagSup
|
|||
} else {
|
||||
memcpy(pSrcBlock->info.parTbName, pValue, TSDB_TABLE_NAME_LEN);
|
||||
}
|
||||
pAPI->streamStateReleaseBuf(pState, NULL, pValue);
|
||||
pAPI->streamStateFreeVal(pValue);
|
||||
}
|
||||
|
||||
static SSDataBlock* buildStreamCreateTableResult(SOperatorInfo* pOperator) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -245,7 +245,7 @@ SNode* createResumeStreamStmt(SAstCreateContext* pCxt, bool ignoreNotExists, boo
|
|||
SNode* createKillStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pId);
|
||||
SNode* createKillQueryStmt(SAstCreateContext* pCxt, const SToken* pQueryId);
|
||||
SNode* createBalanceVgroupStmt(SAstCreateContext* pCxt);
|
||||
SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt);
|
||||
SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt, const SToken* pVgId);
|
||||
SNode* createMergeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId1, const SToken* pVgId2);
|
||||
SNode* createRedistributeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId, SNodeList* pDnodes);
|
||||
SNode* createSplitVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId);
|
||||
|
|
|
@ -691,11 +691,16 @@ cmd ::= KILL TRANSACTION NK_INTEGER(A).
|
|||
|
||||
/************************************************ merge/redistribute/ vgroup ******************************************/
|
||||
cmd ::= BALANCE VGROUP. { pCxt->pRootNode = createBalanceVgroupStmt(pCxt); }
|
||||
cmd ::= BALANCE VGROUP LEADER. { pCxt->pRootNode = createBalanceVgroupLeaderStmt(pCxt); }
|
||||
cmd ::= BALANCE VGROUP LEADER on_vgroup_id(A). { pCxt->pRootNode = createBalanceVgroupLeaderStmt(pCxt, &A); }
|
||||
cmd ::= MERGE VGROUP NK_INTEGER(A) NK_INTEGER(B). { pCxt->pRootNode = createMergeVgroupStmt(pCxt, &A, &B); }
|
||||
cmd ::= REDISTRIBUTE VGROUP NK_INTEGER(A) dnode_list(B). { pCxt->pRootNode = createRedistributeVgroupStmt(pCxt, &A, B); }
|
||||
cmd ::= SPLIT VGROUP NK_INTEGER(A). { pCxt->pRootNode = createSplitVgroupStmt(pCxt, &A); }
|
||||
|
||||
%type on_vgroup_id { SToken }
|
||||
%destructor on_vgroup_id { }
|
||||
on_vgroup_id(A) ::= . { A = nil_token; }
|
||||
on_vgroup_id(A) ::= ON NK_INTEGER(B). { A = B; }
|
||||
|
||||
%type dnode_list { SNodeList* }
|
||||
%destructor dnode_list { nodesDestroyList($$); }
|
||||
dnode_list(A) ::= DNODE NK_INTEGER(B). { A = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B)); }
|
||||
|
|
|
@ -2322,10 +2322,13 @@ SNode* createBalanceVgroupStmt(SAstCreateContext* pCxt) {
|
|||
return (SNode*)pStmt;
|
||||
}
|
||||
|
||||
SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt) {
|
||||
SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt, const SToken* pVgId) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
SBalanceVgroupLeaderStmt* pStmt = (SBalanceVgroupLeaderStmt*)nodesMakeNode(QUERY_NODE_BALANCE_VGROUP_LEADER_STMT);
|
||||
CHECK_OUT_OF_MEM(pStmt);
|
||||
if (NULL != pVgId && NULL != pVgId->z) {
|
||||
pStmt->vgId = taosStr2Int32(pVgId->z, NULL, 10);
|
||||
}
|
||||
return (SNode*)pStmt;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "parInt.h"
|
||||
#include "parTranslater.h"
|
||||
#include "parInt.h"
|
||||
|
||||
#include "catalog.h"
|
||||
#include "cmdnodes.h"
|
||||
|
@ -1211,37 +1211,37 @@ static EDealRes translateNormalValue(STranslateContext* pCxt, SValueNode* pVal,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
if (pVal->node.resType.type != TSDB_DATA_TYPE_BINARY){
|
||||
if (pVal->node.resType.type != TSDB_DATA_TYPE_BINARY) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
|
||||
}
|
||||
|
||||
void* data = NULL;
|
||||
void* data = NULL;
|
||||
uint32_t size = 0;
|
||||
bool isHexChar = isHex(pVal->literal, strlen(pVal->literal));
|
||||
if(isHexChar){
|
||||
if(!isValidateHex(pVal->literal, strlen(pVal->literal))){
|
||||
bool isHexChar = isHex(pVal->literal, strlen(pVal->literal));
|
||||
if (isHexChar) {
|
||||
if (!isValidateHex(pVal->literal, strlen(pVal->literal))) {
|
||||
return TSDB_CODE_PAR_INVALID_VARBINARY;
|
||||
}
|
||||
if(taosHex2Ascii(pVal->literal, strlen(pVal->literal), &data, &size) < 0){
|
||||
if (taosHex2Ascii(pVal->literal, strlen(pVal->literal), &data, &size) < 0) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
size = pVal->node.resType.bytes;
|
||||
data = pVal->literal;
|
||||
}
|
||||
|
||||
if (size + VARSTR_HEADER_SIZE > targetDt.bytes) {
|
||||
if(isHexChar) taosMemoryFree(data);
|
||||
if (isHexChar) taosMemoryFree(data);
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_VALUE_TOO_LONG, pVal->literal);
|
||||
}
|
||||
pVal->datum.p = taosMemoryCalloc(1, size + VARSTR_HEADER_SIZE);
|
||||
if (NULL == pVal->datum.p) {
|
||||
if(isHexChar) taosMemoryFree(data);
|
||||
if (isHexChar) taosMemoryFree(data);
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
||||
}
|
||||
varDataSetLen(pVal->datum.p, size);
|
||||
memcpy(varDataVal(pVal->datum.p), data, size);
|
||||
if(isHexChar) taosMemoryFree(data);
|
||||
if (isHexChar) taosMemoryFree(data);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
|
@ -1777,7 +1777,6 @@ static int32_t translateBlockDistFunc(STranslateContext* pCtx, SFunctionNode* pF
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static bool isStarParam(SNode* pNode) { return nodesIsStar(pNode) || nodesIsTableStar(pNode); }
|
||||
|
||||
static int32_t translateMultiResFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
|
@ -2890,7 +2889,8 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
|||
pJoinTable->table.precision = calcJoinTablePrecision(pJoinTable);
|
||||
pJoinTable->table.singleTable = joinTableIsSingleTable(pJoinTable);
|
||||
code = translateExpr(pCxt, &pJoinTable->pOnCond);
|
||||
pJoinTable->hasSubQuery = (nodeType(pJoinTable->pLeft) != QUERY_NODE_REAL_TABLE) || (nodeType(pJoinTable->pRight) != QUERY_NODE_REAL_TABLE);
|
||||
pJoinTable->hasSubQuery = (nodeType(pJoinTable->pLeft) != QUERY_NODE_REAL_TABLE) ||
|
||||
(nodeType(pJoinTable->pRight) != QUERY_NODE_REAL_TABLE);
|
||||
if (nodeType(pJoinTable->pLeft) == QUERY_NODE_JOIN_TABLE) {
|
||||
((SJoinTableNode*)pJoinTable->pLeft)->isLowLevelJoin = true;
|
||||
}
|
||||
|
@ -2906,7 +2906,7 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createAllColumns(STranslateContext* pCxt, bool igTags, SNodeList** pCols) {
|
||||
static int32_t createAllColumns(STranslateContext* pCxt, bool igTags, SNodeList** pCols) {
|
||||
*pCols = nodesMakeList();
|
||||
if (NULL == *pCols) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY);
|
||||
|
@ -2949,7 +2949,7 @@ static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) {
|
|||
} else {
|
||||
len = snprintf(buf, sizeof(buf) - 1, "%s(%s.%s)", pSrcFunc->functionName, pCol->tableAlias, pCol->colName);
|
||||
taosCreateMD5Hash(buf, len);
|
||||
strncpy(pFunc->node.aliasName, buf, TSDB_COL_NAME_LEN - 1);
|
||||
strncpy(pFunc->node.aliasName, buf, TSDB_COL_NAME_LEN - 1);
|
||||
len = snprintf(buf, sizeof(buf) - 1, "%s(%s)", pSrcFunc->functionName, pCol->colName);
|
||||
// note: userAlias could be truncated here
|
||||
strncpy(pFunc->node.userAlias, buf, TSDB_COL_NAME_LEN - 1);
|
||||
|
@ -3071,11 +3071,8 @@ static int32_t createTags(STranslateContext* pCxt, SNodeList** pOutput) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TD_ENTERPRISE
|
||||
int32_t biRewriteSelectStar(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
int32_t biRewriteSelectStar(STranslateContext* pCxt, SSelectStmt* pSelect) { return TSDB_CODE_SUCCESS; }
|
||||
#endif
|
||||
|
||||
static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
|
@ -3791,7 +3788,8 @@ static int32_t removeConstantValueFromList(SNodeList** pList) {
|
|||
SNode* pNode = NULL;
|
||||
WHERE_EACH(pNode, *pList) {
|
||||
if (nodeType(pNode) == QUERY_NODE_VALUE ||
|
||||
(nodeType(pNode) == QUERY_NODE_FUNCTION && fmIsConstantResFunc((SFunctionNode*)pNode) && fmIsScalarFunc(((SFunctionNode*)pNode)->funcId))) {
|
||||
(nodeType(pNode) == QUERY_NODE_FUNCTION && fmIsConstantResFunc((SFunctionNode*)pNode) &&
|
||||
fmIsScalarFunc(((SFunctionNode*)pNode)->funcId))) {
|
||||
ERASE_NODE(*pList);
|
||||
continue;
|
||||
}
|
||||
|
@ -4636,9 +4634,9 @@ static int32_t checkOptionsDependency(STranslateContext* pCxt, const char* pDbNa
|
|||
daysPerFile = (-1 == daysPerFile ? dbCfg.daysPerFile : daysPerFile);
|
||||
daysToKeep0 = (-1 == daysToKeep0 ? dbCfg.daysToKeep0 : daysToKeep0);
|
||||
}
|
||||
if (daysPerFile > daysToKeep0) {
|
||||
if (daysPerFile > daysToKeep0 / 3) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DB_OPTION,
|
||||
"Invalid duration value, should be keep2 >= keep1 >= keep0 >= duration");
|
||||
"Invalid duration value, should be keep2 >= keep1 >= keep0 >= 3 * duration");
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -7520,6 +7518,7 @@ static int32_t translateBalanceVgroup(STranslateContext* pCxt, SBalanceVgroupStm
|
|||
|
||||
static int32_t translateBalanceVgroupLeader(STranslateContext* pCxt, SBalanceVgroupLeaderStmt* pStmt) {
|
||||
SBalanceVgroupLeaderReq req = {0};
|
||||
req.vgId = pStmt->vgId;
|
||||
return buildCmdMsg(pCxt, TDMT_MND_BALANCE_VGROUP_LEADER, (FSerializeFunc)tSerializeSBalanceVgroupLeaderReq, &req);
|
||||
}
|
||||
|
||||
|
@ -8193,7 +8192,6 @@ static int32_t addShowKindCond(const SShowStmt* pShow, SSelectStmt* pSelect) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int32_t createShowCondition(const SShowStmt* pShow, SSelectStmt* pSelect) {
|
||||
SNode* pDbCond = NULL;
|
||||
SNode* pTbCond = NULL;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3646,32 +3646,73 @@ static SSortLogicNode* partColOptCreateSort(SPartitionLogicNode* pPartition) {
|
|||
}
|
||||
|
||||
static int32_t partitionColsOpt(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SPartitionLogicNode* pNode = (SPartitionLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, partColOptShouldBeOptimized);
|
||||
SNode* node;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SPartitionLogicNode* pNode =
|
||||
(SPartitionLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, partColOptShouldBeOptimized);
|
||||
if (NULL == pNode) return TSDB_CODE_SUCCESS;
|
||||
|
||||
SLogicNode* pRootNode = getLogicNodeRootNode((SLogicNode*)pNode);
|
||||
if (!pRootNode->pHint || !getSortForGroupOptHint(pRootNode->pHint)) {
|
||||
|
||||
|
||||
if (pRootNode->pHint && getSortForGroupOptHint(pRootNode->pHint)) {
|
||||
// replace with sort node
|
||||
SSortLogicNode* pSort = partColOptCreateSort(pNode);
|
||||
if (!pSort) {
|
||||
// if sort create failed, we eat the error, skip the optimization
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
TSWAP(pSort->node.pChildren, pNode->node.pChildren);
|
||||
TSWAP(pSort->node.pTargets, pNode->node.pTargets);
|
||||
optResetParent((SLogicNode*)pSort);
|
||||
pSort->calcGroupId = true;
|
||||
code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pNode, (SLogicNode*)pSort);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
pCxt->optimized = true;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pSort);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
} else if (pNode->node.pParent && nodeType(pNode->node.pParent) == QUERY_NODE_LOGIC_PLAN_AGG) {
|
||||
// Check if we can delete partition node
|
||||
SAggLogicNode* pAgg = (SAggLogicNode*)pNode->node.pParent;
|
||||
FOREACH(node, pNode->pPartitionKeys) {
|
||||
SGroupingSetNode* pgsNode = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
|
||||
if (!pgsNode) code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
pgsNode->groupingSetType = GP_TYPE_NORMAL;
|
||||
pgsNode->pParameterList = nodesMakeList();
|
||||
if (!pgsNode->pParameterList) code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
code = nodesListAppend(pgsNode->pParameterList, nodesCloneNode(node));
|
||||
}
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
// Now we are using hash agg
|
||||
code = nodesListMakeAppend(&pAgg->pGroupKeys, (SNode*)pgsNode);
|
||||
}
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
nodesDestroyNode((SNode*)pgsNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
code =
|
||||
replaceLogicNode(pLogicSubplan, (SLogicNode*)pNode, (SLogicNode*)nodesListGetNode(pNode->node.pChildren, 0));
|
||||
NODES_CLEAR_LIST(pNode->node.pChildren);
|
||||
}
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
// For hash agg, nonblocking mode is meaningless, slimit is useless, so we reset it
|
||||
pAgg->node.forceCreateNonBlockingOptr = false;
|
||||
nodesDestroyNode(pAgg->node.pSlimit);
|
||||
pAgg->node.pSlimit = NULL;
|
||||
nodesDestroyNode((SNode*)pNode);
|
||||
pCxt->optimized = true;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// replace with sort node
|
||||
SSortLogicNode* pSort = partColOptCreateSort(pNode);
|
||||
if (!pSort) {
|
||||
// if sort create failed, we eat the error, skip the optimization
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
TSWAP(pSort->node.pChildren, pNode->node.pChildren);
|
||||
TSWAP(pSort->node.pTargets, pNode->node.pTargets);
|
||||
optResetParent((SLogicNode*)pSort);
|
||||
pSort->calcGroupId = true;
|
||||
code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pNode, (SLogicNode*)pSort);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
pCxt->optimized = true;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pSort);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,11 +65,11 @@ int32_t streamStateCurNext_rocksdb(SStreamState* pState, SStreamStateCur* pCur);
|
|||
int32_t streamStateGetFirst_rocksdb(SStreamState* pState, SWinKey* key);
|
||||
int32_t streamStateGetGroupKVByCur_rocksdb(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateAddIfNotExist_rocksdb(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateCurPrev_rocksdb(SStreamState* pState, SStreamStateCur* pCur);
|
||||
int32_t streamStateCurPrev_rocksdb(SStreamStateCur* pCur);
|
||||
int32_t streamStateGetKVByCur_rocksdb(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
SStreamStateCur* streamStateGetAndCheckCur_rocksdb(SStreamState* pState, SWinKey* key);
|
||||
SStreamStateCur* streamStateSeekKeyNext_rocksdb(SStreamState* pState, const SWinKey* key);
|
||||
SStreamStateCur* streamStateSeekToLast_rocksdb(SStreamState* pState, const SWinKey* key);
|
||||
SStreamStateCur* streamStateSeekToLast_rocksdb(SStreamState* pState);
|
||||
SStreamStateCur* streamStateGetCur_rocksdb(SStreamState* pState, const SWinKey* key);
|
||||
|
||||
// func cf
|
||||
|
@ -84,10 +84,14 @@ int32_t streamStateSessionDel_rocksdb(SStreamState* pState, const SSessionKey* k
|
|||
SStreamStateCur* streamStateSessionSeekKeyCurrentPrev_rocksdb(SStreamState* pState, const SSessionKey* key);
|
||||
SStreamStateCur* streamStateSessionSeekKeyCurrentNext_rocksdb(SStreamState* pState, SSessionKey* key);
|
||||
SStreamStateCur* streamStateSessionSeekKeyNext_rocksdb(SStreamState* pState, const SSessionKey* key);
|
||||
SStreamStateCur* streamStateSessionSeekToLast_rocksdb(SStreamState* pState);
|
||||
int32_t streamStateSessionCurPrev_rocksdb(SStreamStateCur* pCur);
|
||||
|
||||
int32_t streamStateSessionGetKVByCur_rocksdb(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateSessionGetKeyByRange_rocksdb(SStreamState* pState, const SSessionKey* key, SSessionKey* curKey);
|
||||
int32_t streamStateSessionAddIfNotExist_rocksdb(SStreamState* pState, SSessionKey* key, TSKEY gap, void** pVal,
|
||||
int32_t* pVLen);
|
||||
|
||||
int32_t streamStateSessionClear_rocksdb(SStreamState* pState);
|
||||
|
||||
int32_t streamStateStateAddIfNotExist_rocksdb(SStreamState* pState, SSessionKey* key, char* pKeyData,
|
||||
|
|
|
@ -779,7 +779,10 @@ int32_t chkpGetAllDbCfHandle(SStreamMeta* pMeta, rocksdb_column_family_handle_t*
|
|||
int64_t id = *(int64_t*)pIter;
|
||||
|
||||
SBackendCfWrapper* wrapper = taosAcquireRef(streamBackendCfWrapperId, id);
|
||||
if (wrapper == NULL) continue;
|
||||
if (wrapper == NULL) {
|
||||
pIter = taosHashIterate(pMeta->pTaskBackendUnique, pIter);
|
||||
continue;
|
||||
}
|
||||
|
||||
taosThreadRwlockRdlock(&wrapper->rwLock);
|
||||
for (int i = 0; i < sizeof(ginitDict) / sizeof(ginitDict[0]); i++) {
|
||||
|
@ -795,6 +798,10 @@ int32_t chkpGetAllDbCfHandle(SStreamMeta* pMeta, rocksdb_column_family_handle_t*
|
|||
}
|
||||
|
||||
int32_t nCf = taosArrayGetSize(pHandle);
|
||||
if (nCf == 0) {
|
||||
taosArrayDestroy(pHandle);
|
||||
return nCf;
|
||||
}
|
||||
|
||||
rocksdb_column_family_handle_t** ppCf = taosMemoryCalloc(nCf, sizeof(rocksdb_column_family_handle_t*));
|
||||
for (int i = 0; i < nCf; i++) {
|
||||
|
@ -827,6 +834,7 @@ _ERROR:
|
|||
return code;
|
||||
}
|
||||
int32_t chkpPreFlushDb(rocksdb_t* db, rocksdb_column_family_handle_t** cf, int32_t nCf) {
|
||||
if (nCf == 0) return 0;
|
||||
int code = 0;
|
||||
char* err = NULL;
|
||||
|
||||
|
@ -1962,7 +1970,7 @@ int32_t streamStateAddIfNotExist_rocksdb(SStreamState* pState, const SWinKey* ke
|
|||
memset(*pVal, 0, size);
|
||||
return 0;
|
||||
}
|
||||
int32_t streamStateCurPrev_rocksdb(SStreamState* pState, SStreamStateCur* pCur) {
|
||||
int32_t streamStateCurPrev_rocksdb(SStreamStateCur* pCur) {
|
||||
qDebug("streamStateCurPrev_rocksdb");
|
||||
if (!pCur) return -1;
|
||||
|
||||
|
@ -2007,7 +2015,7 @@ SStreamStateCur* streamStateGetAndCheckCur_rocksdb(SStreamState* pState, SWinKey
|
|||
|
||||
SStreamStateCur* streamStateSeekKeyNext_rocksdb(SStreamState* pState, const SWinKey* key) {
|
||||
qDebug("streamStateSeekKeyNext_rocksdb");
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2044,7 +2052,7 @@ SStreamStateCur* streamStateSeekKeyNext_rocksdb(SStreamState* pState, const SWin
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SStreamStateCur* streamStateSeekToLast_rocksdb(SStreamState* pState, const SWinKey* key) {
|
||||
SStreamStateCur* streamStateSeekToLast_rocksdb(SStreamState* pState) {
|
||||
qDebug("streamStateGetCur_rocksdb");
|
||||
int32_t code = 0;
|
||||
|
||||
|
@ -2054,16 +2062,13 @@ SStreamStateCur* streamStateSeekToLast_rocksdb(SStreamState* pState, const SWinK
|
|||
return NULL;
|
||||
}
|
||||
|
||||
char buf[128] = {0};
|
||||
int32_t klen = stateKeyEncode((void*)&maxStateKey, buf);
|
||||
|
||||
{
|
||||
char tbuf[256] = {0};
|
||||
stateKeyToString((void*)&maxStateKey, tbuf);
|
||||
qDebug("seek to last:%s", tbuf);
|
||||
}
|
||||
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) return NULL;
|
||||
|
||||
pCur->number = pState->number;
|
||||
|
@ -2071,6 +2076,8 @@ SStreamStateCur* streamStateSeekToLast_rocksdb(SStreamState* pState, const SWinK
|
|||
pCur->iter = streamStateIterCreate(pState, "state", (rocksdb_snapshot_t**)&pCur->snapshot,
|
||||
(rocksdb_readoptions_t**)&pCur->readOpt);
|
||||
|
||||
char buf[128] = {0};
|
||||
int32_t klen = stateKeyEncode((void*)&maxStateKey, buf);
|
||||
rocksdb_iter_seek(pCur->iter, buf, (size_t)klen);
|
||||
rocksdb_iter_prev(pCur->iter);
|
||||
while (rocksdb_iter_valid(pCur->iter) && iterValueIsStale(pCur->iter)) {
|
||||
|
@ -2090,7 +2097,7 @@ SStreamStateCur* streamStateGetCur_rocksdb(SStreamState* pState, const SWinKey*
|
|||
qDebug("streamStateGetCur_rocksdb");
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) return NULL;
|
||||
|
||||
pCur->db = wrapper->rocksdb;
|
||||
|
@ -2175,11 +2182,57 @@ int32_t streamStateSessionDel_rocksdb(SStreamState* pState, const SSessionKey* k
|
|||
STREAM_STATE_DEL_ROCKSDB(pState, "sess", &sKey);
|
||||
return code;
|
||||
}
|
||||
|
||||
SStreamStateCur* streamStateSessionSeekToLast_rocksdb(SStreamState* pState) {
|
||||
qDebug("streamStateSessionSeekToLast_rocksdb");
|
||||
|
||||
int32_t code = 0;
|
||||
|
||||
SSessionKey maxSessionKey = {.groupId = UINT64_MAX, .win = {.skey = INT64_MAX, .ekey = INT64_MAX}};
|
||||
SStateSessionKey maxKey = {.key = maxSessionKey, .opNum = INT64_MAX};
|
||||
|
||||
STREAM_STATE_PUT_ROCKSDB(pState, "sess", &maxKey, "", 0);
|
||||
if (code != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
pCur->number = pState->number;
|
||||
pCur->db = wrapper->rocksdb;
|
||||
pCur->iter = streamStateIterCreate(pState, "sess", (rocksdb_snapshot_t**)&pCur->snapshot,
|
||||
(rocksdb_readoptions_t**)&pCur->readOpt);
|
||||
|
||||
char buf[128] = {0};
|
||||
int32_t klen = stateSessionKeyEncode((void*)&maxKey, buf);
|
||||
rocksdb_iter_seek(pCur->iter, buf, (size_t)klen);
|
||||
rocksdb_iter_prev(pCur->iter);
|
||||
while (rocksdb_iter_valid(pCur->iter) && iterValueIsStale(pCur->iter)) {
|
||||
rocksdb_iter_prev(pCur->iter);
|
||||
}
|
||||
|
||||
if (!rocksdb_iter_valid(pCur->iter)) {
|
||||
streamStateFreeCur(pCur);
|
||||
pCur = NULL;
|
||||
}
|
||||
|
||||
STREAM_STATE_DEL_ROCKSDB(pState, "sess", &maxKey);
|
||||
return pCur;
|
||||
}
|
||||
|
||||
int32_t streamStateSessionCurPrev_rocksdb(SStreamStateCur* pCur) {
|
||||
qDebug("streamStateCurPrev_rocksdb");
|
||||
if (!pCur) return -1;
|
||||
|
||||
rocksdb_iter_prev(pCur->iter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SStreamStateCur* streamStateSessionSeekKeyCurrentPrev_rocksdb(SStreamState* pState, const SSessionKey* key) {
|
||||
qDebug("streamStateSessionSeekKeyCurrentPrev_rocksdb");
|
||||
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2219,7 +2272,7 @@ SStreamStateCur* streamStateSessionSeekKeyCurrentPrev_rocksdb(SStreamState* pSta
|
|||
SStreamStateCur* streamStateSessionSeekKeyCurrentNext_rocksdb(SStreamState* pState, SSessionKey* key) {
|
||||
qDebug("streamStateSessionSeekKeyCurrentNext_rocksdb");
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2257,7 +2310,7 @@ SStreamStateCur* streamStateSessionSeekKeyCurrentNext_rocksdb(SStreamState* pSta
|
|||
SStreamStateCur* streamStateSessionSeekKeyNext_rocksdb(SStreamState* pState, const SSessionKey* key) {
|
||||
qDebug("streamStateSessionSeekKeyNext_rocksdb");
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2293,6 +2346,7 @@ SStreamStateCur* streamStateSessionSeekKeyNext_rocksdb(SStreamState* pState, con
|
|||
}
|
||||
return pCur;
|
||||
}
|
||||
|
||||
int32_t streamStateSessionGetKVByCur_rocksdb(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen) {
|
||||
qDebug("streamStateSessionGetKVByCur_rocksdb");
|
||||
if (!pCur) {
|
||||
|
@ -2358,7 +2412,7 @@ int32_t streamStateFillDel_rocksdb(SStreamState* pState, const SWinKey* key) {
|
|||
|
||||
SStreamStateCur* streamStateFillGetCur_rocksdb(SStreamState* pState, const SWinKey* key) {
|
||||
qDebug("streamStateFillGetCur_rocksdb");
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
|
||||
if (pCur == NULL) return NULL;
|
||||
|
@ -2419,7 +2473,7 @@ int32_t streamStateFillGetKVByCur_rocksdb(SStreamStateCur* pCur, SWinKey* pKey,
|
|||
SStreamStateCur* streamStateFillSeekKeyNext_rocksdb(SStreamState* pState, const SWinKey* key) {
|
||||
qDebug("streamStateFillSeekKeyNext_rocksdb");
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (!pCur) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2457,7 +2511,7 @@ SStreamStateCur* streamStateFillSeekKeyNext_rocksdb(SStreamState* pState, const
|
|||
SStreamStateCur* streamStateFillSeekKeyPrev_rocksdb(SStreamState* pState, const SWinKey* key) {
|
||||
qDebug("streamStateFillSeekKeyPrev_rocksdb");
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2495,7 +2549,7 @@ SStreamStateCur* streamStateFillSeekKeyPrev_rocksdb(SStreamState* pState, const
|
|||
int32_t streamStateSessionGetKeyByRange_rocksdb(SStreamState* pState, const SSessionKey* key, SSessionKey* curKey) {
|
||||
qDebug("streamStateSessionGetKeyByRange_rocksdb");
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
if (pCur == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -2765,7 +2819,7 @@ int32_t streamDefaultIterGet_rocksdb(SStreamState* pState, const void* start, co
|
|||
return code;
|
||||
}
|
||||
void* streamDefaultIterCreate_rocksdb(SStreamState* pState) {
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
SStreamStateCur* pCur = createStreamStateCursor();
|
||||
SBackendCfWrapper* wrapper = pState->pTdbState->pBackendCfWrapper;
|
||||
|
||||
pCur->db = wrapper->rocksdb;
|
||||
|
|
|
@ -238,8 +238,6 @@ int32_t streamMetaReopen(SStreamMeta* pMeta, int64_t chkpId) {
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
taosMemoryFree(defaultPath);
|
||||
taosMemoryFree(newPath);
|
||||
|
||||
pMeta->streamBackend = streamBackendInit(pMeta->path, pMeta->chkpId);
|
||||
while (pMeta->streamBackend == NULL) {
|
||||
|
@ -254,6 +252,8 @@ int32_t streamMetaReopen(SStreamMeta* pMeta, int64_t chkpId) {
|
|||
pMeta->streamBackendRid = taosAddRef(streamBackendId, pMeta->streamBackend);
|
||||
streamBackendLoadCheckpointInfo(pMeta);
|
||||
|
||||
taosMemoryFree(defaultPath);
|
||||
taosMemoryFree(newPath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,583 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tstreamFileState.h"
|
||||
|
||||
#include "query.h"
|
||||
#include "streamBackendRocksdb.h"
|
||||
#include "taos.h"
|
||||
#include "tcommon.h"
|
||||
#include "thash.h"
|
||||
#include "tsimplehash.h"
|
||||
|
||||
|
||||
typedef int (*__session_compare_fn_t) (const SSessionKey* pWin, const void* pDatas, int pos);
|
||||
|
||||
int sessionStateKeyCompare(const SSessionKey* pWin1, const void* pDatas, int pos) {
|
||||
SRowBuffPos* pPos2 = taosArrayGetP(pDatas, pos);
|
||||
SSessionKey* pWin2 = (SSessionKey*) pPos2->pKey;
|
||||
return sessionWinKeyCmpr(pWin1, pWin2);
|
||||
}
|
||||
|
||||
int32_t binarySearch(void* keyList, int num, const void* key, __session_compare_fn_t cmpFn) {
|
||||
int firstPos = 0, lastPos = num - 1, midPos = -1;
|
||||
int numOfRows = 0;
|
||||
|
||||
if (num <= 0) return -1;
|
||||
// find the first position which is smaller or equal than the key.
|
||||
// if all data is bigger than the key return -1
|
||||
while (1) {
|
||||
if (cmpFn(key, keyList, lastPos) >= 0) return lastPos;
|
||||
if (cmpFn(key, keyList, firstPos) == 0) return firstPos;
|
||||
if (cmpFn(key, keyList, firstPos) < 0) return firstPos - 1;
|
||||
|
||||
numOfRows = lastPos - firstPos + 1;
|
||||
midPos = (numOfRows >> 1) + firstPos;
|
||||
|
||||
if (cmpFn(key, keyList, midPos) < 0) {
|
||||
lastPos = midPos - 1;
|
||||
} else if (cmpFn(key, keyList, midPos) > 0) {
|
||||
firstPos = midPos + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return midPos;
|
||||
}
|
||||
|
||||
int64_t getSessionWindowEndkey(void* data, int32_t index) {
|
||||
SArray* pWinInfos = (SArray*)data;
|
||||
SRowBuffPos** ppos = taosArrayGet(pWinInfos, index);
|
||||
SSessionKey* pWin = (SSessionKey*)((*ppos)->pKey);
|
||||
return pWin->win.ekey;
|
||||
}
|
||||
|
||||
bool inSessionWindow(SSessionKey* pKey, TSKEY ts, int64_t gap) {
|
||||
if (ts + gap >= pKey->win.skey && ts - gap <= pKey->win.ekey) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static SRowBuffPos* addNewSessionWindow(SStreamFileState* pFileState, SArray* pWinInfos, SSessionKey* pKey) {
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pFileState);
|
||||
ASSERT(pNewPos->pRowBuff);
|
||||
memcpy(pNewPos->pKey, pKey, sizeof(SSessionKey));
|
||||
taosArrayPush(pWinInfos, &pNewPos);
|
||||
return pNewPos;
|
||||
}
|
||||
|
||||
static SRowBuffPos* insertNewSessionWindow(SStreamFileState* pFileState, SArray* pWinInfos, SSessionKey* pKey, int32_t index) {
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pFileState);
|
||||
ASSERT(pNewPos->pRowBuff);
|
||||
memcpy(pNewPos->pKey, pKey, sizeof(SSessionKey));
|
||||
taosArrayInsert(pWinInfos, index, &pNewPos);
|
||||
return pNewPos;
|
||||
}
|
||||
|
||||
SRowBuffPos* createSessionWinBuff(SStreamFileState* pFileState, SSessionKey* pKey, void* p, int32_t* pVLen) {
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pFileState);
|
||||
memcpy(pNewPos->pKey, pKey, sizeof(SSessionKey));
|
||||
pNewPos->needFree = true;
|
||||
memcpy(pNewPos->pRowBuff, p, *pVLen);
|
||||
taosMemoryFree(p);
|
||||
return pNewPos;
|
||||
}
|
||||
|
||||
int32_t getSessionWinResultBuff(SStreamFileState* pFileState, SSessionKey* pKey, TSKEY gap, void** pVal, int32_t* pVLen) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SSHashObj* pSessionBuff = getRowStateBuff(pFileState);
|
||||
SArray* pWinStates = NULL;
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pKey->groupId, sizeof(uint64_t));
|
||||
if (ppBuff) {
|
||||
pWinStates = (SArray*)(*ppBuff);
|
||||
} else {
|
||||
pWinStates = taosArrayInit(16, POINTER_BYTES);
|
||||
tSimpleHashPut(pSessionBuff, &pKey->groupId, sizeof(uint64_t), &pWinStates, POINTER_BYTES);
|
||||
}
|
||||
|
||||
TSKEY startTs = pKey->win.skey;
|
||||
TSKEY endTs = pKey->win.ekey;
|
||||
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
if (size == 0) {
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
void* p = NULL;
|
||||
int32_t code_file = streamStateSessionAddIfNotExist_rocksdb(pFileStore, pKey, gap, &p, pVLen);
|
||||
if (code_file == TSDB_CODE_SUCCESS) {
|
||||
(*pVal) = createSessionWinBuff(pFileState, pKey, p, pVLen);
|
||||
code = code_file;
|
||||
qDebug("===stream===0 get session win:%" PRId64 ",%" PRId64 " from disc, res %d", startTs, endTs, code_file);
|
||||
} else {
|
||||
(*pVal) = addNewSessionWindow(pFileState, pWinStates, pKey);
|
||||
code = TSDB_CODE_FAILED;
|
||||
taosMemoryFree(p);
|
||||
}
|
||||
goto _end;
|
||||
}
|
||||
|
||||
// find the first position which is smaller than the pKey
|
||||
int32_t index = binarySearch(pWinStates, size, pKey, sessionStateKeyCompare);
|
||||
SRowBuffPos* pPos = NULL;
|
||||
|
||||
if (index >= 0) {
|
||||
pPos = taosArrayGetP(pWinStates, index);
|
||||
if (inSessionWindow(pPos->pKey, startTs, gap)) {
|
||||
(*pVal) = pPos;
|
||||
SSessionKey* pDestWinKey = (SSessionKey*)pPos->pKey;
|
||||
pPos->beUsed = true;
|
||||
*pKey = *pDestWinKey;
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
|
||||
if (index + 1 < size) {
|
||||
pPos = taosArrayGetP(pWinStates, index + 1);
|
||||
if (inSessionWindow(pPos->pKey, startTs, gap) || (endTs != INT64_MIN && inSessionWindow(pPos->pKey, endTs, gap)) ) {
|
||||
(*pVal) = pPos;
|
||||
SSessionKey* pDestWinKey = (SSessionKey*)pPos->pKey;
|
||||
pPos->beUsed = true;
|
||||
*pKey = *pDestWinKey;
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
|
||||
if (index + 1 == 0) {
|
||||
if (!isDeteled(pFileState, endTs) && isFlushedState(pFileState, endTs, gap)) {
|
||||
void* p = NULL;
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
int32_t code_file = streamStateSessionAddIfNotExist_rocksdb(pFileStore, pKey, gap, &p, pVLen);
|
||||
if (code_file == TSDB_CODE_SUCCESS || isFlushedState(pFileState, endTs, 0)) {
|
||||
(*pVal) = createSessionWinBuff(pFileState, pKey, p, pVLen);
|
||||
code = code_file;
|
||||
qDebug("===stream===1 get session win:%" PRId64 ",%" PRId64 " from disc, res %d", startTs, endTs, code_file);
|
||||
goto _end;
|
||||
} else {
|
||||
taosMemoryFree(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index == size - 1) {
|
||||
(*pVal) = addNewSessionWindow(pFileState, pWinStates, pKey);
|
||||
code = TSDB_CODE_FAILED;
|
||||
goto _end;
|
||||
}
|
||||
(*pVal) = insertNewSessionWindow(pFileState, pWinStates, pKey, index + 1);
|
||||
code = TSDB_CODE_FAILED;
|
||||
|
||||
_end:
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t putSessionWinResultBuff(SStreamFileState* pFileState, SRowBuffPos* pPos) {
|
||||
SSHashObj* pSessionBuff = getRowStateBuff(pFileState);
|
||||
SSessionKey* pKey = pPos->pKey;
|
||||
SArray* pWinStates = NULL;
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pKey->groupId, sizeof(uint64_t));
|
||||
if (ppBuff) {
|
||||
pWinStates = (SArray*)(*ppBuff);
|
||||
} else {
|
||||
pWinStates = taosArrayInit(16, POINTER_BYTES);
|
||||
tSimpleHashPut(pSessionBuff, &pKey->groupId, sizeof(uint64_t), &pWinStates, POINTER_BYTES);
|
||||
}
|
||||
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
if (size == 0) {
|
||||
taosArrayPush(pWinStates, &pPos);
|
||||
goto _end;
|
||||
}
|
||||
|
||||
// find the first position which is smaller than the pKey
|
||||
int32_t index = binarySearch(pWinStates, size, pKey, sessionStateKeyCompare);
|
||||
if (index >= 0) {
|
||||
taosArrayInsert(pWinStates, index, &pPos);
|
||||
} else {
|
||||
taosArrayInsert(pWinStates, 0, &pPos);
|
||||
}
|
||||
|
||||
_end:
|
||||
pPos->needFree = false;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t getSessionFlushedBuff(SStreamFileState* pFileState, SSessionKey* pKey, void** pVal, int32_t* pVLen) {
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pFileState);
|
||||
memcpy(pNewPos->pKey, pKey, sizeof(SSessionKey));
|
||||
pNewPos->needFree = true;
|
||||
void* pBuff = NULL;
|
||||
int32_t code = streamStateSessionGet_rocksdb(getStateFileStore(pFileState), pKey, &pBuff, pVLen);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
memcpy(pNewPos->pRowBuff, pBuff, *pVLen);
|
||||
taosMemoryFreeClear(pBuff);
|
||||
(*pVal) = pNewPos;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t deleteSessionWinStateBuffFn(void* pBuff, const void *key, size_t keyLen) {
|
||||
SSHashObj* pSessionBuff = (SSHashObj*) pBuff;
|
||||
SSessionKey* pWinKey = (SSessionKey*) key;
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pWinKey->groupId, sizeof(uint64_t));
|
||||
if (!ppBuff) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
SArray* pWinStates = (SArray*)(*ppBuff);
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
TSKEY gap = 0;
|
||||
int32_t index = binarySearch(pWinStates, size, pWinKey, sessionStateKeyCompare);
|
||||
if (index >= 0) {
|
||||
SRowBuffPos* pPos = taosArrayGetP(pWinStates, index);
|
||||
if (inSessionWindow(pPos->pKey, pWinKey->win.skey, gap)) {
|
||||
pPos->beFlushed = true;
|
||||
taosArrayRemove(pWinStates, index);
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t deleteSessionWinStateBuffByPosFn(SStreamFileState* pFileState, SRowBuffPos* pPos) {
|
||||
SSHashObj* pSessionBuff = getRowStateBuff(pFileState);
|
||||
SSessionKey* pWinKey = (SSessionKey*) pPos->pKey;
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pWinKey->groupId, sizeof(uint64_t));
|
||||
if (!ppBuff) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
SArray* pWinStates = (SArray*)(*ppBuff);
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
TSKEY gap = 0;
|
||||
int32_t index = binarySearch(pWinStates, size, pWinKey, sessionStateKeyCompare);
|
||||
if (index >= 0) {
|
||||
SRowBuffPos* pItemPos = taosArrayGetP(pWinStates, index);
|
||||
if (pItemPos == pPos) {
|
||||
taosArrayRemove(pWinStates, index);
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void sessionWinStateClear(SStreamFileState* pFileState) {
|
||||
int32_t buffSize = getRowStateRowSize(pFileState);
|
||||
void* pIte = NULL;
|
||||
size_t keyLen = 0;
|
||||
int32_t iter = 0;
|
||||
void* pBuff = getRowStateBuff(pFileState);
|
||||
while ((pIte = tSimpleHashIterate(pBuff, pIte, &iter)) != NULL) {
|
||||
SArray* pWinStates = *((void**)pIte);
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
SRowBuffPos* pPos = taosArrayGetP(pWinStates, i);
|
||||
memset(pPos->pRowBuff, 0, buffSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sessionWinStateCleanup(void* pBuff) {
|
||||
void* pIte = NULL;
|
||||
size_t keyLen = 0;
|
||||
int32_t iter = 0;
|
||||
while ((pIte = tSimpleHashIterate(pBuff, pIte, &iter)) != NULL) {
|
||||
SArray* pWinStates = (SArray*) (*(void**)pIte);
|
||||
taosArrayDestroy(pWinStates);
|
||||
}
|
||||
tSimpleHashCleanup(pBuff);
|
||||
}
|
||||
|
||||
static SStreamStateCur* seekKeyCurrentPrev_buff(SStreamFileState* pFileState, const SSessionKey* pWinKey,
|
||||
SArray** pWins, int32_t* pIndex) {
|
||||
SStreamStateCur* pCur = NULL;
|
||||
SSHashObj* pSessionBuff = getRowStateBuff(pFileState);
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pWinKey->groupId, sizeof(uint64_t));
|
||||
if (!ppBuff) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SArray* pWinStates = (SArray*)(*ppBuff);
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
TSKEY gap = 0;
|
||||
int32_t index = binarySearch(pWinStates, size, pWinKey, sessionStateKeyCompare);
|
||||
|
||||
if (pWins) {
|
||||
(*pWins) = pWinStates;
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
pCur = createStreamStateCursor();
|
||||
pCur->buffIndex = index;
|
||||
pCur->pStreamFileState = pFileState;
|
||||
if (pIndex) {
|
||||
*pIndex = index;
|
||||
}
|
||||
}
|
||||
return pCur;
|
||||
}
|
||||
|
||||
SStreamStateCur* sessionWinStateSeekKeyCurrentPrev(SStreamFileState* pFileState, const SSessionKey* pWinKey) {
|
||||
SStreamStateCur* pCur = seekKeyCurrentPrev_buff(pFileState, pWinKey, NULL, NULL);
|
||||
if (pCur) {
|
||||
return pCur;
|
||||
}
|
||||
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
pCur = streamStateSessionSeekKeyCurrentPrev_rocksdb(pFileStore, pWinKey);
|
||||
if (!pCur) {
|
||||
return NULL;
|
||||
}
|
||||
pCur->buffIndex = -1;
|
||||
pCur->pStreamFileState = pFileState;
|
||||
return pCur;
|
||||
}
|
||||
static void transformCursor(SStreamFileState* pFileState, SStreamStateCur* pCur) {
|
||||
if (!pCur) {
|
||||
return;
|
||||
}
|
||||
streamStateResetCur(pCur);
|
||||
pCur->buffIndex = 0;
|
||||
pCur->pStreamFileState = pFileState;
|
||||
}
|
||||
|
||||
static void checkAndTransformCursor(SStreamFileState* pFileState, const uint64_t groupId, SArray* pWinStates, SStreamStateCur** ppCur) {
|
||||
SSessionKey key = {.groupId = groupId};
|
||||
int32_t code = streamStateSessionGetKVByCur_rocksdb(*ppCur, &key, NULL, NULL);
|
||||
if (taosArrayGetSize(pWinStates) > 0 && (code == TSDB_CODE_FAILED || sessionStateKeyCompare(&key, pWinStates, 0) >= 0)) {
|
||||
if ( !(*ppCur) ) {
|
||||
(*ppCur) = createStreamStateCursor();
|
||||
}
|
||||
transformCursor(pFileState, *ppCur);
|
||||
} else if (*ppCur) {
|
||||
(*ppCur)->buffIndex = -1;
|
||||
(*ppCur)->pStreamFileState = pFileState;
|
||||
}
|
||||
}
|
||||
|
||||
SStreamStateCur* sessionWinStateSeekKeyCurrentNext(SStreamFileState* pFileState, const SSessionKey* pWinKey) {
|
||||
SArray* pWinStates = NULL;
|
||||
int32_t index = -1;
|
||||
SStreamStateCur* pCur = seekKeyCurrentPrev_buff(pFileState, pWinKey, &pWinStates, &index);
|
||||
if (pCur) {
|
||||
if (sessionStateKeyCompare(pWinKey, pWinStates, index) > 0) {
|
||||
sessionWinStateMoveToNext(pCur);
|
||||
}
|
||||
return pCur;
|
||||
}
|
||||
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
pCur = streamStateSessionSeekKeyCurrentNext_rocksdb(pFileStore, (SSessionKey*)pWinKey);
|
||||
checkAndTransformCursor(pFileState, pWinKey->groupId, pWinStates, &pCur);
|
||||
return pCur;
|
||||
}
|
||||
|
||||
SStreamStateCur* sessionWinStateSeekKeyNext(SStreamFileState* pFileState, const SSessionKey* pWinKey) {
|
||||
SArray* pWinStates = NULL;
|
||||
int32_t index = -1;
|
||||
SStreamStateCur* pCur = seekKeyCurrentPrev_buff(pFileState, pWinKey, &pWinStates, &index);
|
||||
if (pCur) {
|
||||
sessionWinStateMoveToNext(pCur);
|
||||
return pCur;
|
||||
}
|
||||
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
pCur = streamStateSessionSeekKeyNext_rocksdb(pFileStore, pWinKey);
|
||||
checkAndTransformCursor(pFileState, pWinKey->groupId, pWinStates, &pCur);
|
||||
return pCur;
|
||||
}
|
||||
|
||||
int32_t sessionWinStateGetKVByCur(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen) {
|
||||
if (!pCur) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SSHashObj* pSessionBuff = getRowStateBuff(pCur->pStreamFileState);
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pKey->groupId, sizeof(uint64_t));
|
||||
if (!ppBuff) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
SArray* pWinStates = (SArray*)(*ppBuff);
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
if (pCur->buffIndex >= 0) {
|
||||
if (pCur->buffIndex >= size) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
SRowBuffPos* pPos = taosArrayGetP(pWinStates, pCur->buffIndex);
|
||||
if (pVal) {
|
||||
*pVal = pPos;
|
||||
}
|
||||
*pKey = *(SSessionKey*)(pPos->pKey);
|
||||
} else {
|
||||
void* pData = NULL;
|
||||
code = streamStateSessionGetKVByCur_rocksdb(pCur, pKey, &pData, pVLen);
|
||||
if (taosArrayGetSize(pWinStates) > 0 && (code == TSDB_CODE_FAILED || sessionStateKeyCompare(pKey, pWinStates, 0) >= 0)) {
|
||||
transformCursor(pCur->pStreamFileState, pCur);
|
||||
SRowBuffPos* pPos = taosArrayGetP(pWinStates, pCur->buffIndex);
|
||||
if (pVal) {
|
||||
*pVal = pPos;
|
||||
}
|
||||
*pKey = *(SSessionKey*)(pPos->pKey);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
} else if (code == TSDB_CODE_SUCCESS && pVal) {
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pCur->pStreamFileState);
|
||||
memcpy(pNewPos->pKey, pKey, sizeof(SSessionKey));
|
||||
pNewPos->needFree = true;
|
||||
memcpy(pNewPos->pRowBuff, pData, *pVLen);
|
||||
(*pVal) = pNewPos;
|
||||
}
|
||||
taosMemoryFreeClear(pData);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t sessionWinStateMoveToNext(SStreamStateCur* pCur) {
|
||||
if (pCur && pCur->buffIndex >= 0) {
|
||||
pCur->buffIndex++;
|
||||
} else {
|
||||
streamStateCurNext_rocksdb(NULL, pCur);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t sessionWinStateGetKeyByRange(SStreamFileState* pFileState, const SSessionKey* key, SSessionKey* curKey) {
|
||||
SStreamStateCur* pCur = sessionWinStateSeekKeyCurrentPrev(pFileState, key);
|
||||
SSessionKey tmpKey = *key;
|
||||
int32_t code = sessionWinStateGetKVByCur(pCur, &tmpKey, NULL, NULL);
|
||||
bool hasCurrentPrev = true;
|
||||
if (code == TSDB_CODE_FAILED) {
|
||||
streamStateFreeCur(pCur);
|
||||
pCur = sessionWinStateSeekKeyNext(pFileState, key);
|
||||
code = sessionWinStateGetKVByCur(pCur, &tmpKey, NULL, NULL);
|
||||
hasCurrentPrev = false;
|
||||
}
|
||||
|
||||
if (code == TSDB_CODE_FAILED) {
|
||||
code = TSDB_CODE_FAILED;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
if (sessionRangeKeyCmpr(key, &tmpKey) == 0) {
|
||||
*curKey = tmpKey;
|
||||
goto _end;
|
||||
} else if (!hasCurrentPrev) {
|
||||
code = TSDB_CODE_FAILED;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
sessionWinStateMoveToNext(pCur);
|
||||
code = sessionWinStateGetKVByCur(pCur, &tmpKey, NULL, NULL);
|
||||
if (code == TSDB_CODE_SUCCESS && sessionRangeKeyCmpr(key, &tmpKey) == 0) {
|
||||
*curKey = tmpKey;
|
||||
} else {
|
||||
code = TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
_end:
|
||||
streamStateFreeCur(pCur);
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t getStateWinResultBuff(SStreamFileState* pFileState, SSessionKey* key, char* pKeyData, int32_t keyDataLen,
|
||||
state_key_cmpr_fn fn, void** pVal, int32_t* pVLen) {
|
||||
SSessionKey* pWinKey = key;
|
||||
TSKEY gap = 0;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SSHashObj* pSessionBuff = getRowStateBuff(pFileState);
|
||||
SArray* pWinStates = NULL;
|
||||
void** ppBuff = tSimpleHashGet(pSessionBuff, &pWinKey->groupId, sizeof(uint64_t));
|
||||
if (ppBuff) {
|
||||
pWinStates = (SArray*)(*ppBuff);
|
||||
} else {
|
||||
pWinStates = taosArrayInit(16, POINTER_BYTES);
|
||||
tSimpleHashPut(pSessionBuff, &pWinKey->groupId, sizeof(uint64_t), &pWinStates, POINTER_BYTES);
|
||||
}
|
||||
|
||||
TSKEY startTs = pWinKey->win.skey;
|
||||
TSKEY endTs = pWinKey->win.ekey;
|
||||
|
||||
int32_t size = taosArrayGetSize(pWinStates);
|
||||
if (size == 0) {
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
void* p = NULL;
|
||||
int32_t code_file = streamStateStateAddIfNotExist_rocksdb(pFileStore, pWinKey, pKeyData, keyDataLen, fn, &p, pVLen);
|
||||
if (code_file == TSDB_CODE_SUCCESS) {
|
||||
(*pVal) = createSessionWinBuff(pFileState, pWinKey, p, pVLen);
|
||||
code = code_file;
|
||||
qDebug("===stream===0 get state win:%" PRId64 ",%" PRId64 " from disc, res %d", pWinKey->win.skey, pWinKey->win.ekey, code_file);
|
||||
} else {
|
||||
(*pVal) = addNewSessionWindow(pFileState, pWinStates, key);
|
||||
code = TSDB_CODE_FAILED;
|
||||
taosMemoryFree(p);
|
||||
}
|
||||
goto _end;
|
||||
}
|
||||
|
||||
// find the first position which is smaller than the pWinKey
|
||||
int32_t index = binarySearch(pWinStates, size, pWinKey, sessionStateKeyCompare);
|
||||
SRowBuffPos* pPos = NULL;
|
||||
int32_t valSize = *pVLen;
|
||||
|
||||
if (index >= 0) {
|
||||
pPos = taosArrayGetP(pWinStates, index);
|
||||
void* stateKey = (char*)(pPos->pRowBuff) + (valSize - keyDataLen);
|
||||
if (inSessionWindow(pPos->pKey, startTs, gap) || fn(pKeyData, stateKey) == true) {
|
||||
(*pVal) = pPos;
|
||||
SSessionKey* pDestWinKey = (SSessionKey*)pPos->pKey;
|
||||
pPos->beUsed = true;
|
||||
*key = *pDestWinKey;
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
|
||||
if (index + 1 < size) {
|
||||
pPos = taosArrayGetP(pWinStates, index + 1);
|
||||
void* stateKey = (char*)(pPos->pRowBuff) + (valSize - keyDataLen);
|
||||
if (inSessionWindow(pPos->pKey, startTs, gap) || (endTs != INT64_MIN && inSessionWindow(pPos->pKey, endTs, gap)) || fn(pKeyData, stateKey) == true) {
|
||||
(*pVal) = pPos;
|
||||
SSessionKey* pDestWinKey = (SSessionKey*)pPos->pKey;
|
||||
pPos->beUsed = true;
|
||||
*key = *pDestWinKey;
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
|
||||
if (index + 1 == 0) {
|
||||
if (!isDeteled(pFileState, endTs)) {
|
||||
void* p = NULL;
|
||||
void* pFileStore = getStateFileStore(pFileState);
|
||||
int32_t code_file =
|
||||
streamStateStateAddIfNotExist_rocksdb(pFileStore, pWinKey, pKeyData, keyDataLen, fn, &p, pVLen);
|
||||
if (code_file == TSDB_CODE_SUCCESS || isFlushedState(pFileState, endTs, 0)) {
|
||||
(*pVal) = createSessionWinBuff(pFileState, pWinKey, p, pVLen);
|
||||
code = code_file;
|
||||
qDebug("===stream===1 get state win:%" PRId64 ",%" PRId64 " from disc, res %d", pWinKey->win.skey, pWinKey->win.ekey, code_file);
|
||||
goto _end;
|
||||
} else {
|
||||
taosMemoryFree(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index == size - 1) {
|
||||
(*pVal) = addNewSessionWindow(pFileState, pWinStates, key);
|
||||
code = TSDB_CODE_FAILED;
|
||||
goto _end;
|
||||
}
|
||||
(*pVal) = insertNewSessionWindow(pFileState, pWinStates, key, index + 1);
|
||||
code = TSDB_CODE_FAILED;
|
||||
|
||||
_end:
|
||||
return code;
|
||||
}
|
|
@ -351,7 +351,7 @@ bool streamStateCheck(SStreamState* pState, const SWinKey* key) {
|
|||
|
||||
int32_t streamStateGetByPos(SStreamState* pState, void* pos, void** pVal) {
|
||||
int32_t code = getRowBuffByPos(pState->pFileState, pos, pVal);
|
||||
releaseRowBuffPos(pos);
|
||||
streamFileStateReleaseBuff(pState->pFileState, pos, false);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -395,9 +395,6 @@ int32_t streamStateFillDel(SStreamState* pState, const SWinKey* key) {
|
|||
int32_t streamStateClear(SStreamState* pState) {
|
||||
#ifdef USE_ROCKSDB
|
||||
streamFileStateClear(pState->pFileState);
|
||||
if (needClearDiskBuff(pState->pFileState)) {
|
||||
streamStateClear_rocksdb(pState);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
SWinKey key = {.ts = 0, .groupId = 0};
|
||||
|
@ -422,19 +419,16 @@ void streamStateSetNumber(SStreamState* pState, int32_t number) { pState->number
|
|||
int32_t streamStateSaveInfo(SStreamState* pState, void* pKey, int32_t keyLen, void* pVal, int32_t vLen) {
|
||||
#ifdef USE_ROCKSDB
|
||||
int32_t code = 0;
|
||||
void* batch = streamStateCreateBatch();
|
||||
|
||||
code = streamStatePutBatch(pState, "default", batch, pKey, pVal, vLen, 0);
|
||||
char* cfName = "default";
|
||||
void* batch = streamStateCreateBatch();
|
||||
code = streamStatePutBatch(pState, cfName, batch, pKey, pVal, vLen, 0);
|
||||
if (code != 0) {
|
||||
streamStateDestroyBatch(batch);
|
||||
return code;
|
||||
}
|
||||
code = streamStatePutBatch_rocksdb(pState, batch);
|
||||
streamStateDestroyBatch(batch);
|
||||
// code = streamDefaultPut_rocksdb(pState, pKey, pVal, vLen);
|
||||
// char* Val = NULL;
|
||||
// int32_t len = 0;
|
||||
// code = streamDefaultGet_rocksdb(pState, pKey, (void**)&Val, &len);
|
||||
return code;
|
||||
#else
|
||||
return 0;
|
||||
|
@ -466,20 +460,24 @@ int32_t streamStateAddIfNotExist(SStreamState* pState, const SWinKey* key, void*
|
|||
#endif
|
||||
}
|
||||
|
||||
int32_t streamStateReleaseBuf(SStreamState* pState, const SWinKey* key, void* pVal) {
|
||||
int32_t streamStateReleaseBuf(SStreamState* pState, void* pVal, bool used) {
|
||||
// todo refactor
|
||||
qDebug("streamStateReleaseBuf");
|
||||
if (!pVal) {
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_ROCKSDB
|
||||
taosMemoryFree(pVal);
|
||||
streamFileStateReleaseBuff(pState->pFileState, pVal, used);
|
||||
#else
|
||||
streamStateFreeVal(pVal);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t streamStateClearBuff(SStreamState* pState, void* pVal) {
|
||||
return streamFileStateClearBuff(pState->pFileState, pVal);
|
||||
}
|
||||
|
||||
SStreamStateCur* streamStateFillGetCur(SStreamState* pState, const SWinKey* key) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateFillGetCur_rocksdb(pState, key);
|
||||
|
@ -569,39 +567,6 @@ int32_t streamStateGetGroupKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const v
|
|||
#endif
|
||||
}
|
||||
|
||||
int32_t streamStateGetFirst(SStreamState* pState, SWinKey* key) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateGetFirst_rocksdb(pState, key);
|
||||
#else
|
||||
// todo refactor
|
||||
SWinKey tmp = {.ts = 0, .groupId = 0};
|
||||
streamStatePut(pState, &tmp, NULL, 0);
|
||||
SStreamStateCur* pCur = streamStateSeekKeyNext(pState, &tmp);
|
||||
int32_t code = streamStateGetKVByCur(pCur, key, NULL, 0);
|
||||
streamStateFreeCur(pCur);
|
||||
streamStateDel(pState, &tmp);
|
||||
return code;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t streamStateSeekFirst(SStreamState* pState, SStreamStateCur* pCur) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_iter_seek_to_first(pCur->iter);
|
||||
return 0;
|
||||
#else
|
||||
return tdbTbcMoveToFirst(pCur->pCur);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t streamStateSeekLast(SStreamState* pState, SStreamStateCur* pCur) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_iter_seek_to_last(pCur->iter);
|
||||
return 0;
|
||||
#else
|
||||
return tdbTbcMoveToLast(pCur->pCur);
|
||||
#endif
|
||||
}
|
||||
|
||||
SStreamStateCur* streamStateSeekKeyNext(SStreamState* pState, const SWinKey* key) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSeekKeyNext_rocksdb(pState, key);
|
||||
|
@ -693,7 +658,7 @@ SStreamStateCur* streamStateFillSeekKeyPrev(SStreamState* pState, const SWinKey*
|
|||
|
||||
int32_t streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateCurNext_rocksdb(pState, pCur);
|
||||
return sessionWinStateMoveToNext(pCur);
|
||||
#else
|
||||
if (!pCur) {
|
||||
return -1;
|
||||
|
@ -705,7 +670,7 @@ int32_t streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur) {
|
|||
|
||||
int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateCurPrev_rocksdb(pState, pCur);
|
||||
return streamStateCurPrev_rocksdb(pCur);
|
||||
#else
|
||||
if (!pCur) {
|
||||
return -1;
|
||||
|
@ -713,16 +678,29 @@ int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur) {
|
|||
return tdbTbcMoveToPrev(pCur->pCur);
|
||||
#endif
|
||||
}
|
||||
void streamStateFreeCur(SStreamStateCur* pCur) {
|
||||
|
||||
void streamStateResetCur(SStreamStateCur* pCur) {
|
||||
if (!pCur) {
|
||||
return;
|
||||
}
|
||||
qDebug("streamStateFreeCur");
|
||||
rocksdb_iter_destroy(pCur->iter);
|
||||
if (pCur->iter) rocksdb_iter_destroy(pCur->iter);
|
||||
if (pCur->snapshot) rocksdb_release_snapshot(pCur->db, pCur->snapshot);
|
||||
rocksdb_readoptions_destroy(pCur->readOpt);
|
||||
if (pCur->readOpt) rocksdb_readoptions_destroy(pCur->readOpt);
|
||||
|
||||
tdbTbcClose(pCur->pCur);
|
||||
|
||||
memset(pCur, 0, sizeof(SStreamStateCur));
|
||||
|
||||
pCur->buffIndex = -1;
|
||||
}
|
||||
|
||||
void streamStateFreeCur(SStreamStateCur* pCur) {
|
||||
if (!pCur || pCur->buffIndex >= 0) {
|
||||
taosMemoryFree(pCur);
|
||||
return;
|
||||
}
|
||||
qDebug("streamStateFreeCur");
|
||||
streamStateResetCur(pCur);
|
||||
taosMemoryFree(pCur);
|
||||
}
|
||||
|
||||
|
@ -734,11 +712,25 @@ void streamStateFreeVal(void* val) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int32_t streamStateSessionPut(SStreamState* pState, const SSessionKey* key, const void* value, int32_t vLen) {
|
||||
int32_t streamStateSessionPut(SStreamState* pState, const SSessionKey* key, void* value, int32_t vLen) {
|
||||
#ifdef USE_ROCKSDB
|
||||
qDebug("===stream===save skey:%" PRId64 ", ekey:%" PRId64 ", groupId:%" PRIu64, key->win.skey, key->win.ekey,
|
||||
key->groupId);
|
||||
return streamStateSessionPut_rocksdb(pState, key, value, vLen);
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SRowBuffPos* pos = (SRowBuffPos*)value;
|
||||
if (pos->needFree) {
|
||||
if (isFlushedState(pState->pFileState, key->win.ekey, 0)) {
|
||||
if (!pos->pRowBuff) {
|
||||
return code;
|
||||
}
|
||||
code = streamStateSessionPut_rocksdb(pState, key, pos->pRowBuff, vLen);
|
||||
streamStateReleaseBuf(pState, pos, true);
|
||||
putFreeBuff(pState->pFileState, pos);
|
||||
qDebug("===stream===save skey:%" PRId64 ", ekey:%" PRId64 ", groupId:%" PRIu64 ".code:%d", key->win.skey,
|
||||
key->win.ekey, key->groupId, code);
|
||||
} else {
|
||||
code = putSessionWinResultBuff(pState->pFileState, value);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
#else
|
||||
SStateSessionKey sKey = {.key = *key, .opNum = pState->number};
|
||||
return tdbTbUpsert(pState->pTdbState->pSessionStateDb, &sKey, sizeof(SStateSessionKey), value, vLen,
|
||||
|
@ -748,7 +740,7 @@ int32_t streamStateSessionPut(SStreamState* pState, const SSessionKey* key, cons
|
|||
|
||||
int32_t streamStateSessionGet(SStreamState* pState, SSessionKey* key, void** pVal, int32_t* pVLen) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionGet_rocksdb(pState, key, pVal, pVLen);
|
||||
return getSessionFlushedBuff(pState->pFileState, key, pVal, pVLen);
|
||||
#else
|
||||
|
||||
SStreamStateCur* pCur = streamStateSessionSeekKeyCurrentNext(pState, key);
|
||||
|
@ -773,7 +765,7 @@ int32_t streamStateSessionDel(SStreamState* pState, const SSessionKey* key) {
|
|||
#ifdef USE_ROCKSDB
|
||||
qDebug("===stream===delete skey:%" PRId64 ", ekey:%" PRId64 ", groupId:%" PRIu64, key->win.skey, key->win.ekey,
|
||||
key->groupId);
|
||||
return streamStateSessionDel_rocksdb(pState, key);
|
||||
return deleteRowBuff(pState->pFileState, key, sizeof(SSessionKey));
|
||||
#else
|
||||
SStateSessionKey sKey = {.key = *key, .opNum = pState->number};
|
||||
return tdbTbDelete(pState->pTdbState->pSessionStateDb, &sKey, sizeof(SStateSessionKey), pState->pTdbState->txn);
|
||||
|
@ -782,7 +774,7 @@ int32_t streamStateSessionDel(SStreamState* pState, const SSessionKey* key) {
|
|||
|
||||
SStreamStateCur* streamStateSessionSeekKeyCurrentPrev(SStreamState* pState, const SSessionKey* key) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionSeekKeyCurrentPrev_rocksdb(pState, key);
|
||||
return sessionWinStateSeekKeyCurrentPrev(pState->pFileState, key);
|
||||
#else
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
if (pCur == NULL) {
|
||||
|
@ -813,7 +805,7 @@ SStreamStateCur* streamStateSessionSeekKeyCurrentPrev(SStreamState* pState, cons
|
|||
|
||||
SStreamStateCur* streamStateSessionSeekKeyCurrentNext(SStreamState* pState, const SSessionKey* key) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionSeekKeyCurrentNext_rocksdb(pState, (SSessionKey*)key);
|
||||
return sessionWinStateSeekKeyCurrentNext(pState->pFileState, key);
|
||||
#else
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
if (pCur == NULL) {
|
||||
|
@ -845,7 +837,7 @@ SStreamStateCur* streamStateSessionSeekKeyCurrentNext(SStreamState* pState, cons
|
|||
|
||||
SStreamStateCur* streamStateSessionSeekKeyNext(SStreamState* pState, const SSessionKey* key) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionSeekKeyNext_rocksdb(pState, key);
|
||||
return sessionWinStateSeekKeyNext(pState->pFileState, key);
|
||||
#else
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
if (pCur == NULL) {
|
||||
|
@ -876,7 +868,7 @@ SStreamStateCur* streamStateSessionSeekKeyNext(SStreamState* pState, const SSess
|
|||
|
||||
int32_t streamStateSessionGetKVByCur(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionGetKVByCur_rocksdb(pCur, pKey, pVal, pVLen);
|
||||
return sessionWinStateGetKVByCur(pCur, pKey, pVal, pVLen);
|
||||
#else
|
||||
if (!pCur) {
|
||||
return -1;
|
||||
|
@ -899,6 +891,7 @@ int32_t streamStateSessionGetKVByCur(SStreamStateCur* pCur, SSessionKey* pKey, v
|
|||
|
||||
int32_t streamStateSessionClear(SStreamState* pState) {
|
||||
#ifdef USE_ROCKSDB
|
||||
sessionWinStateClear(pState->pFileState);
|
||||
return streamStateSessionClear_rocksdb(pState);
|
||||
#else
|
||||
SSessionKey key = {.win.skey = 0, .win.ekey = 0, .groupId = 0};
|
||||
|
@ -923,7 +916,7 @@ int32_t streamStateSessionClear(SStreamState* pState) {
|
|||
|
||||
int32_t streamStateSessionGetKeyByRange(SStreamState* pState, const SSessionKey* key, SSessionKey* curKey) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionGetKeyByRange_rocksdb(pState, key, curKey);
|
||||
return sessionWinStateGetKeyByRange(pState->pFileState, key, curKey);
|
||||
#else
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
if (pCur == NULL) {
|
||||
|
@ -976,7 +969,7 @@ int32_t streamStateSessionGetKeyByRange(SStreamState* pState, const SSessionKey*
|
|||
int32_t streamStateSessionAddIfNotExist(SStreamState* pState, SSessionKey* key, TSKEY gap, void** pVal,
|
||||
int32_t* pVLen) {
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateSessionAddIfNotExist_rocksdb(pState, key, gap, pVal, pVLen);
|
||||
return getSessionWinResultBuff(pState->pFileState, key, gap, pVal, pVLen);
|
||||
#else
|
||||
// todo refactor
|
||||
int32_t res = 0;
|
||||
|
@ -1032,7 +1025,7 @@ int32_t streamStateStateAddIfNotExist(SStreamState* pState, SSessionKey* key, ch
|
|||
// todo refactor
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
return streamStateStateAddIfNotExist_rocksdb(pState, key, pKeyData, keyDataLen, fn, pVal, pVLen);
|
||||
return getStateWinResultBuff(pState->pFileState, key, pKeyData, keyDataLen, fn, pVal, pVLen);
|
||||
#else
|
||||
int32_t res = 0;
|
||||
SSessionKey tmpKey = *key;
|
||||
|
@ -1143,6 +1136,12 @@ int32_t streamStateDeleteCheckPoint(SStreamState* pState, TSKEY mark) {
|
|||
|
||||
void streamStateReloadInfo(SStreamState* pState, TSKEY ts) { streamFileStateReloadInfo(pState->pFileState, ts); }
|
||||
|
||||
SStreamStateCur* createStreamStateCursor() {
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
pCur->buffIndex = -1;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
#if 0
|
||||
char* streamStateSessionDump(SStreamState* pState) {
|
||||
SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur));
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "tstreamFileState.h"
|
||||
|
||||
#include "query.h"
|
||||
#include "storageapi.h"
|
||||
#include "streamBackendRocksdb.h"
|
||||
#include "taos.h"
|
||||
#include "tcommon.h"
|
||||
|
@ -29,29 +28,94 @@
|
|||
#define MIN_NUM_OF_ROW_BUFF 10240
|
||||
|
||||
struct SStreamFileState {
|
||||
SList* usedBuffs;
|
||||
SList* freeBuffs;
|
||||
SSHashObj* rowBuffMap;
|
||||
void* pFileStore;
|
||||
int32_t rowSize;
|
||||
int32_t selectivityRowSize;
|
||||
int32_t keyLen;
|
||||
uint64_t preCheckPointVersion;
|
||||
uint64_t checkPointVersion;
|
||||
TSKEY maxTs;
|
||||
TSKEY deleteMark;
|
||||
TSKEY flushMark;
|
||||
uint64_t maxRowCount;
|
||||
uint64_t curRowCount;
|
||||
GetTsFun getTs;
|
||||
char* id;
|
||||
SList* usedBuffs;
|
||||
SList* freeBuffs;
|
||||
void* rowStateBuff;
|
||||
void* pFileStore;
|
||||
int32_t rowSize;
|
||||
int32_t selectivityRowSize;
|
||||
int32_t keyLen;
|
||||
uint64_t preCheckPointVersion;
|
||||
uint64_t checkPointVersion;
|
||||
TSKEY maxTs;
|
||||
TSKEY deleteMark;
|
||||
TSKEY flushMark;
|
||||
uint64_t maxRowCount;
|
||||
uint64_t curRowCount;
|
||||
GetTsFun getTs;
|
||||
char* id;
|
||||
char* cfName;
|
||||
|
||||
_state_buff_cleanup_fn stateBuffCleanupFn;
|
||||
_state_buff_remove_fn stateBuffRemoveFn;
|
||||
_state_buff_remove_by_pos_fn stateBuffRemoveByPosFn;
|
||||
_state_buff_create_statekey_fn stateBuffCreateStateKeyFn;
|
||||
|
||||
_state_file_remove_fn stateFileRemoveFn;
|
||||
_state_file_get_fn stateFileGetFn;
|
||||
_state_file_clear_fn stateFileClearFn;
|
||||
};
|
||||
|
||||
typedef SRowBuffPos SRowBuffInfo;
|
||||
|
||||
int32_t stateHashBuffRemoveFn(void* pBuff, const void* pKey, size_t keyLen) {
|
||||
SRowBuffPos** pos = tSimpleHashGet(pBuff, pKey, keyLen);
|
||||
if (pos) {
|
||||
(*pos)->beFlushed = true;
|
||||
}
|
||||
return tSimpleHashRemove(pBuff, pKey, keyLen);
|
||||
}
|
||||
|
||||
int32_t stateHashBuffRemoveByPosFn(SStreamFileState* pFileState, SRowBuffPos* pPos) {
|
||||
size_t keyLen = pFileState->keyLen;
|
||||
SRowBuffPos** ppPos = tSimpleHashGet(pFileState->rowStateBuff, pPos->pKey, keyLen);
|
||||
if (ppPos) {
|
||||
if ((*ppPos) == pPos) {
|
||||
return tSimpleHashRemove(pFileState->rowStateBuff, pPos->pKey, keyLen);
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void stateHashBuffClearFn(void* pBuff) { tSimpleHashClear(pBuff); }
|
||||
|
||||
void stateHashBuffCleanupFn(void* pBuff) { tSimpleHashCleanup(pBuff); }
|
||||
|
||||
int32_t intervalFileRemoveFn(SStreamFileState* pFileState, const void* pKey) {
|
||||
return streamStateDel_rocksdb(pFileState->pFileStore, pKey);
|
||||
}
|
||||
|
||||
int32_t intervalFileGetFn(SStreamFileState* pFileState, void* pKey, void* data, int32_t* pDataLen) {
|
||||
return streamStateGet_rocksdb(pFileState->pFileStore, pKey, data, pDataLen);
|
||||
}
|
||||
|
||||
void* intervalCreateStateKey(SRowBuffPos* pPos, int64_t num) {
|
||||
SStateKey* pStateKey = taosMemoryCalloc(1, sizeof(SStateKey));
|
||||
SWinKey* pWinKey = pPos->pKey;
|
||||
pStateKey->key = *pWinKey;
|
||||
pStateKey->opNum = num;
|
||||
return pStateKey;
|
||||
}
|
||||
|
||||
int32_t sessionFileRemoveFn(SStreamFileState* pFileState, const void* pKey) {
|
||||
return streamStateSessionDel_rocksdb(pFileState->pFileStore, pKey);
|
||||
}
|
||||
|
||||
int32_t sessionFileGetFn(SStreamFileState* pFileState, void* pKey, void* data, int32_t* pDataLen) {
|
||||
return streamStateSessionGet_rocksdb(pFileState->pFileStore, pKey, data, pDataLen);
|
||||
}
|
||||
|
||||
void* sessionCreateStateKey(SRowBuffPos* pPos, int64_t num) {
|
||||
SStateSessionKey* pStateKey = taosMemoryCalloc(1, sizeof(SStateSessionKey));
|
||||
SSessionKey* pWinKey = pPos->pKey;
|
||||
pStateKey->key = *pWinKey;
|
||||
pStateKey->opNum = num;
|
||||
return pStateKey;
|
||||
}
|
||||
|
||||
SStreamFileState* streamFileStateInit(int64_t memSize, uint32_t keySize, uint32_t rowSize, uint32_t selectRowSize,
|
||||
GetTsFun fp, void* pFile, TSKEY delMark, const char* taskId,
|
||||
int64_t checkpointId) {
|
||||
GetTsFun fp, void* pFile, TSKEY delMark, const char* taskId, int64_t checkpointId,
|
||||
int8_t type) {
|
||||
if (memSize <= 0) {
|
||||
memSize = DEFAULT_MAX_STREAM_BUFFER_SIZE;
|
||||
}
|
||||
|
@ -69,8 +133,31 @@ SStreamFileState* streamFileStateInit(int64_t memSize, uint32_t keySize, uint32_
|
|||
pFileState->freeBuffs = tdListNew(POINTER_BYTES);
|
||||
_hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
|
||||
int32_t cap = TMIN(MIN_NUM_OF_ROW_BUFF, pFileState->maxRowCount);
|
||||
pFileState->rowBuffMap = tSimpleHashInit(cap, hashFn);
|
||||
if (!pFileState->usedBuffs || !pFileState->freeBuffs || !pFileState->rowBuffMap) {
|
||||
if (type == STREAM_STATE_BUFF_HASH) {
|
||||
pFileState->rowStateBuff = tSimpleHashInit(cap, hashFn);
|
||||
pFileState->stateBuffCleanupFn = stateHashBuffCleanupFn;
|
||||
pFileState->stateBuffRemoveFn = stateHashBuffRemoveFn;
|
||||
pFileState->stateBuffRemoveByPosFn = stateHashBuffRemoveByPosFn;
|
||||
pFileState->stateBuffCreateStateKeyFn = intervalCreateStateKey;
|
||||
|
||||
pFileState->stateFileRemoveFn = intervalFileRemoveFn;
|
||||
pFileState->stateFileGetFn = intervalFileGetFn;
|
||||
pFileState->stateFileClearFn = streamStateClear_rocksdb;
|
||||
pFileState->cfName = taosStrdup("state");
|
||||
} else {
|
||||
pFileState->rowStateBuff = tSimpleHashInit(cap, hashFn);
|
||||
pFileState->stateBuffCleanupFn = sessionWinStateCleanup;
|
||||
pFileState->stateBuffRemoveFn = deleteSessionWinStateBuffFn;
|
||||
pFileState->stateBuffRemoveByPosFn = deleteSessionWinStateBuffByPosFn;
|
||||
pFileState->stateBuffCreateStateKeyFn = sessionCreateStateKey;
|
||||
|
||||
pFileState->stateFileRemoveFn = sessionFileRemoveFn;
|
||||
pFileState->stateFileGetFn = sessionFileGetFn;
|
||||
pFileState->stateFileClearFn = streamStateSessionClear_rocksdb;
|
||||
pFileState->cfName = taosStrdup("sess");
|
||||
}
|
||||
|
||||
if (!pFileState->usedBuffs || !pFileState->freeBuffs || !pFileState->rowStateBuff) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
|
@ -87,7 +174,10 @@ SStreamFileState* streamFileStateInit(int64_t memSize, uint32_t keySize, uint32_
|
|||
pFileState->maxTs = INT64_MIN;
|
||||
pFileState->id = taosStrdup(taskId);
|
||||
|
||||
recoverSnapshot(pFileState, checkpointId);
|
||||
// todo(liuyao) optimize
|
||||
if (type == STREAM_STATE_BUFF_HASH) {
|
||||
recoverSnapshot(pFileState, checkpointId);
|
||||
}
|
||||
return pFileState;
|
||||
|
||||
_error:
|
||||
|
@ -132,12 +222,20 @@ void streamFileStateDestroy(SStreamFileState* pFileState) {
|
|||
}
|
||||
|
||||
taosMemoryFree(pFileState->id);
|
||||
taosMemoryFree(pFileState->cfName);
|
||||
tdListFreeP(pFileState->usedBuffs, destroyRowBuffAllPosPtr);
|
||||
tdListFreeP(pFileState->freeBuffs, destroyRowBuff);
|
||||
tSimpleHashCleanup(pFileState->rowBuffMap);
|
||||
pFileState->stateBuffCleanupFn(pFileState->rowStateBuff);
|
||||
taosMemoryFree(pFileState);
|
||||
}
|
||||
|
||||
void putFreeBuff(SStreamFileState* pFileState, SRowBuffPos* pPos) {
|
||||
if (pPos->pRowBuff) {
|
||||
tdListAppend(pFileState->freeBuffs, &(pPos->pRowBuff));
|
||||
pPos->pRowBuff = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void clearExpiredRowBuff(SStreamFileState* pFileState, TSKEY ts, bool all) {
|
||||
SListIter iter = {0};
|
||||
tdListInitIter(pFileState->usedBuffs, &iter, TD_LIST_FORWARD);
|
||||
|
@ -146,11 +244,10 @@ void clearExpiredRowBuff(SStreamFileState* pFileState, TSKEY ts, bool all) {
|
|||
while ((pNode = tdListNext(&iter)) != NULL) {
|
||||
SRowBuffPos* pPos = *(SRowBuffPos**)(pNode->data);
|
||||
if (all || (pFileState->getTs(pPos->pKey) < ts && !pPos->beUsed)) {
|
||||
ASSERT(pPos->pRowBuff != NULL);
|
||||
tdListAppend(pFileState->freeBuffs, &(pPos->pRowBuff));
|
||||
pPos->pRowBuff = NULL;
|
||||
putFreeBuff(pFileState, pPos);
|
||||
|
||||
if (!all) {
|
||||
tSimpleHashRemove(pFileState->rowBuffMap, pPos->pKey, pFileState->keyLen);
|
||||
pFileState->stateBuffRemoveByPosFn(pFileState, pPos);
|
||||
}
|
||||
destroyRowBuffPos(pPos);
|
||||
tdListPopNode(pFileState->usedBuffs, pNode);
|
||||
|
@ -159,15 +256,38 @@ void clearExpiredRowBuff(SStreamFileState* pFileState, TSKEY ts, bool all) {
|
|||
}
|
||||
}
|
||||
|
||||
void clearFlushedRowBuff(SStreamFileState* pFileState, SStreamSnapshot* pFlushList, uint64_t max) {
|
||||
uint64_t i = 0;
|
||||
SListIter iter = {0};
|
||||
tdListInitIter(pFileState->usedBuffs, &iter, TD_LIST_FORWARD);
|
||||
|
||||
SListNode* pNode = NULL;
|
||||
while ((pNode = tdListNext(&iter)) != NULL && i < max) {
|
||||
SRowBuffPos* pPos = *(SRowBuffPos**)pNode->data;
|
||||
if (isFlushedState(pFileState, pFileState->getTs(pPos->pKey), 0) && !pPos->beUsed) {
|
||||
tdListAppend(pFlushList, &pPos);
|
||||
pFileState->flushMark = TMAX(pFileState->flushMark, pFileState->getTs(pPos->pKey));
|
||||
pFileState->stateBuffRemoveByPosFn(pFileState, pPos);
|
||||
tdListPopNode(pFileState->usedBuffs, pNode);
|
||||
taosMemoryFreeClear(pNode);
|
||||
if (pPos->pRowBuff) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void streamFileStateClear(SStreamFileState* pFileState) {
|
||||
pFileState->flushMark = INT64_MIN;
|
||||
pFileState->maxTs = INT64_MIN;
|
||||
tSimpleHashClear(pFileState->rowBuffMap);
|
||||
tSimpleHashClear(pFileState->rowStateBuff);
|
||||
clearExpiredRowBuff(pFileState, 0, true);
|
||||
}
|
||||
|
||||
bool needClearDiskBuff(SStreamFileState* pFileState) { return pFileState->flushMark > 0; }
|
||||
|
||||
void streamFileStateReleaseBuff(SStreamFileState* pFileState, SRowBuffPos* pPos, bool used) { pPos->beUsed = used; }
|
||||
|
||||
void popUsedBuffs(SStreamFileState* pFileState, SStreamSnapshot* pFlushList, uint64_t max, bool used) {
|
||||
uint64_t i = 0;
|
||||
SListIter iter = {0};
|
||||
|
@ -179,10 +299,12 @@ void popUsedBuffs(SStreamFileState* pFileState, SStreamSnapshot* pFlushList, uin
|
|||
if (pPos->beUsed == used) {
|
||||
tdListAppend(pFlushList, &pPos);
|
||||
pFileState->flushMark = TMAX(pFileState->flushMark, pFileState->getTs(pPos->pKey));
|
||||
tSimpleHashRemove(pFileState->rowBuffMap, pPos->pKey, pFileState->keyLen);
|
||||
pFileState->stateBuffRemoveByPosFn(pFileState, pPos);
|
||||
tdListPopNode(pFileState->usedBuffs, pNode);
|
||||
taosMemoryFreeClear(pNode);
|
||||
i++;
|
||||
if (pPos->pRowBuff) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,10 +319,13 @@ int32_t flushRowBuff(SStreamFileState* pFileState) {
|
|||
|
||||
uint64_t num = (uint64_t)(pFileState->curRowCount * FLUSH_RATIO);
|
||||
num = TMAX(num, FLUSH_NUM);
|
||||
popUsedBuffs(pFileState, pFlushList, num, false);
|
||||
|
||||
clearFlushedRowBuff(pFileState, pFlushList, num);
|
||||
if (isListEmpty(pFlushList)) {
|
||||
popUsedBuffs(pFileState, pFlushList, num, true);
|
||||
popUsedBuffs(pFileState, pFlushList, num, false);
|
||||
|
||||
if (isListEmpty(pFlushList)) {
|
||||
popUsedBuffs(pFileState, pFlushList, num, true);
|
||||
}
|
||||
}
|
||||
|
||||
flushSnapshot(pFileState, pFlushList, false);
|
||||
|
@ -210,9 +335,7 @@ int32_t flushRowBuff(SStreamFileState* pFileState) {
|
|||
SListNode* pNode = NULL;
|
||||
while ((pNode = tdListNext(&fIter)) != NULL) {
|
||||
SRowBuffPos* pPos = *(SRowBuffPos**)pNode->data;
|
||||
ASSERT(pPos->pRowBuff != NULL);
|
||||
tdListAppend(pFileState->freeBuffs, &pPos->pRowBuff);
|
||||
pPos->pRowBuff = NULL;
|
||||
putFreeBuff(pFileState, pPos);
|
||||
}
|
||||
|
||||
tdListFreeP(pFlushList, destroyRowBuffPosPtr);
|
||||
|
@ -227,7 +350,9 @@ int32_t clearRowBuff(SStreamFileState* pFileState) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void* getFreeBuff(SList* lists, int32_t buffSize) {
|
||||
void* getFreeBuff(SStreamFileState* pFileState) {
|
||||
SList* lists = pFileState->freeBuffs;
|
||||
int32_t buffSize = pFileState->rowSize;
|
||||
SListNode* pNode = tdListPopHead(lists);
|
||||
if (!pNode) {
|
||||
return NULL;
|
||||
|
@ -238,10 +363,18 @@ void* getFreeBuff(SList* lists, int32_t buffSize) {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
int32_t streamFileStateClearBuff(SStreamFileState* pFileState, SRowBuffPos* pPos) {
|
||||
if (pPos->pRowBuff) {
|
||||
memset(pPos->pRowBuff, 0, pFileState->rowSize);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
SRowBuffPos* getNewRowPos(SStreamFileState* pFileState) {
|
||||
SRowBuffPos* pPos = taosMemoryCalloc(1, sizeof(SRowBuffPos));
|
||||
pPos->pKey = taosMemoryCalloc(1, pFileState->keyLen);
|
||||
void* pBuff = getFreeBuff(pFileState->freeBuffs, pFileState->rowSize);
|
||||
void* pBuff = getFreeBuff(pFileState);
|
||||
if (pBuff) {
|
||||
pPos->pRowBuff = pBuff;
|
||||
goto _end;
|
||||
|
@ -258,7 +391,7 @@ SRowBuffPos* getNewRowPos(SStreamFileState* pFileState) {
|
|||
|
||||
int32_t code = clearRowBuff(pFileState);
|
||||
ASSERT(code == 0);
|
||||
pPos->pRowBuff = getFreeBuff(pFileState->freeBuffs, pFileState->rowSize);
|
||||
pPos->pRowBuff = getFreeBuff(pFileState);
|
||||
|
||||
_end:
|
||||
tdListAppend(pFileState->usedBuffs, &pPos);
|
||||
|
@ -266,9 +399,17 @@ _end:
|
|||
return pPos;
|
||||
}
|
||||
|
||||
SRowBuffPos* getNewRowPosForWrite(SStreamFileState* pFileState) {
|
||||
SRowBuffPos* newPos = getNewRowPos(pFileState);
|
||||
newPos->beUsed = true;
|
||||
newPos->beFlushed = false;
|
||||
newPos->needFree = false;
|
||||
return newPos;
|
||||
}
|
||||
|
||||
int32_t getRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen, void** pVal, int32_t* pVLen) {
|
||||
pFileState->maxTs = TMAX(pFileState->maxTs, pFileState->getTs(pKey));
|
||||
SRowBuffPos** pos = tSimpleHashGet(pFileState->rowBuffMap, pKey, keyLen);
|
||||
SRowBuffPos** pos = tSimpleHashGet(pFileState->rowStateBuff, pKey, keyLen);
|
||||
if (pos) {
|
||||
*pVLen = pFileState->rowSize;
|
||||
*pVal = *pos;
|
||||
|
@ -276,14 +417,12 @@ int32_t getRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen, voi
|
|||
(*pos)->beFlushed = false;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
SRowBuffPos* pNewPos = getNewRowPos(pFileState);
|
||||
pNewPos->beUsed = true;
|
||||
pNewPos->beFlushed = false;
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pFileState);
|
||||
ASSERT(pNewPos->pRowBuff);
|
||||
memcpy(pNewPos->pKey, pKey, keyLen);
|
||||
|
||||
TSKEY ts = pFileState->getTs(pKey);
|
||||
if (ts > pFileState->maxTs - pFileState->deleteMark && ts < pFileState->flushMark) {
|
||||
if (!isDeteled(pFileState, ts) && isFlushedState(pFileState, ts, 0)) {
|
||||
int32_t len = 0;
|
||||
void* p = NULL;
|
||||
int32_t code = streamStateGet_rocksdb(pFileState->pFileStore, pKey, &p, &len);
|
||||
|
@ -294,7 +433,7 @@ int32_t getRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen, voi
|
|||
taosMemoryFree(p);
|
||||
}
|
||||
|
||||
tSimpleHashPut(pFileState->rowBuffMap, pKey, keyLen, &pNewPos, POINTER_BYTES);
|
||||
tSimpleHashPut(pFileState->rowStateBuff, pKey, keyLen, &pNewPos, POINTER_BYTES);
|
||||
if (pVal) {
|
||||
*pVLen = pFileState->rowSize;
|
||||
*pVal = pNewPos;
|
||||
|
@ -303,45 +442,60 @@ int32_t getRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen, voi
|
|||
}
|
||||
|
||||
int32_t deleteRowBuff(SStreamFileState* pFileState, const void* pKey, int32_t keyLen) {
|
||||
int32_t code_buff = tSimpleHashRemove(pFileState->rowBuffMap, pKey, keyLen);
|
||||
int32_t code_rocks = streamStateDel_rocksdb(pFileState->pFileStore, pKey);
|
||||
return code_buff == TSDB_CODE_SUCCESS ? code_buff : code_rocks;
|
||||
int32_t code_buff = pFileState->stateBuffRemoveFn(pFileState->rowStateBuff, pKey, keyLen);
|
||||
int32_t code_file = pFileState->stateFileRemoveFn(pFileState, pKey);
|
||||
if (code_buff == TSDB_CODE_SUCCESS || code_file == TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
static void recoverSessionRowBuff(SStreamFileState* pFileState, SRowBuffPos* pPos) {
|
||||
int32_t len = 0;
|
||||
void* pBuff = NULL;
|
||||
pFileState->stateFileGetFn(pFileState, pPos->pKey, &pBuff, &len);
|
||||
memcpy(pPos->pRowBuff, pBuff, len);
|
||||
taosMemoryFree(pBuff);
|
||||
}
|
||||
|
||||
int32_t getRowBuffByPos(SStreamFileState* pFileState, SRowBuffPos* pPos, void** pVal) {
|
||||
if (pPos->pRowBuff) {
|
||||
if (pPos->needFree) {
|
||||
recoverSessionRowBuff(pFileState, pPos);
|
||||
}
|
||||
(*pVal) = pPos->pRowBuff;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
pPos->pRowBuff = getFreeBuff(pFileState->freeBuffs, pFileState->rowSize);
|
||||
pPos->pRowBuff = getFreeBuff(pFileState);
|
||||
if (!pPos->pRowBuff) {
|
||||
int32_t code = clearRowBuff(pFileState);
|
||||
ASSERT(code == 0);
|
||||
pPos->pRowBuff = getFreeBuff(pFileState->freeBuffs, pFileState->rowSize);
|
||||
if (pFileState->curRowCount < pFileState->maxRowCount) {
|
||||
pPos->pRowBuff = taosMemoryCalloc(1, pFileState->rowSize);
|
||||
pFileState->curRowCount++;
|
||||
} else {
|
||||
int32_t code = clearRowBuff(pFileState);
|
||||
ASSERT(code == 0);
|
||||
pPos->pRowBuff = getFreeBuff(pFileState);
|
||||
}
|
||||
ASSERT(pPos->pRowBuff);
|
||||
}
|
||||
|
||||
int32_t len = 0;
|
||||
void* pBuff = NULL;
|
||||
streamStateGet_rocksdb(pFileState->pFileStore, pPos->pKey, &pBuff, &len);
|
||||
memcpy(pPos->pRowBuff, pBuff, len);
|
||||
taosMemoryFree(pBuff);
|
||||
recoverSessionRowBuff(pFileState, pPos);
|
||||
(*pVal) = pPos->pRowBuff;
|
||||
tdListPrepend(pFileState->usedBuffs, &pPos);
|
||||
if (!pPos->needFree) {
|
||||
tdListPrepend(pFileState->usedBuffs, &pPos);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
bool hasRowBuff(SStreamFileState* pFileState, void* pKey, int32_t keyLen) {
|
||||
SRowBuffPos** pos = tSimpleHashGet(pFileState->rowBuffMap, pKey, keyLen);
|
||||
SRowBuffPos** pos = tSimpleHashGet(pFileState->rowStateBuff, pKey, keyLen);
|
||||
if (pos) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void releaseRowBuffPos(SRowBuffPos* pBuff) { pBuff->beUsed = false; }
|
||||
|
||||
SStreamSnapshot* getSnapshot(SStreamFileState* pFileState) {
|
||||
int64_t mark = (INT64_MIN + pFileState->deleteMark >= pFileState->maxTs) ? INT64_MIN
|
||||
: pFileState->maxTs - pFileState->deleteMark;
|
||||
|
@ -349,13 +503,13 @@ SStreamSnapshot* getSnapshot(SStreamFileState* pFileState) {
|
|||
return pFileState->usedBuffs;
|
||||
}
|
||||
|
||||
void streamFileStateDecode(TSKEY* key, void* pBuff, int32_t len) { pBuff = taosDecodeFixedI64(pBuff, key); }
|
||||
void streamFileStateDecode(TSKEY* pKey, void* pBuff, int32_t len) { pBuff = taosDecodeFixedI64(pBuff, pKey); }
|
||||
|
||||
void streamFileStateEncode(TSKEY* key, void** pVal, int32_t* pLen) {
|
||||
void streamFileStateEncode(TSKEY* pKey, void** pVal, int32_t* pLen) {
|
||||
*pLen = sizeof(TSKEY);
|
||||
(*pVal) = taosMemoryCalloc(1, *pLen);
|
||||
void* buff = *pVal;
|
||||
taosEncodeFixedI64(&buff, *key);
|
||||
taosEncodeFixedI64(&buff, *pKey);
|
||||
}
|
||||
|
||||
int32_t flushSnapshot(SStreamFileState* pFileState, SStreamSnapshot* pSnapshot, bool flushState) {
|
||||
|
@ -369,7 +523,7 @@ int32_t flushSnapshot(SStreamFileState* pFileState, SStreamSnapshot* pSnapshot,
|
|||
int32_t numOfElems = listNEles(pSnapshot);
|
||||
SListNode* pNode = NULL;
|
||||
|
||||
int idx = streamStateGetCfIdx(pFileState->pFileStore, "state");
|
||||
int idx = streamStateGetCfIdx(pFileState->pFileStore, pFileState->cfName);
|
||||
|
||||
int32_t len = pFileState->rowSize + sizeof(uint64_t) + sizeof(int32_t) + 1;
|
||||
char* buf = taosMemoryCalloc(1, len);
|
||||
|
@ -377,23 +531,23 @@ int32_t flushSnapshot(SStreamFileState* pFileState, SStreamSnapshot* pSnapshot,
|
|||
void* batch = streamStateCreateBatch();
|
||||
while ((pNode = tdListNext(&iter)) != NULL && code == TSDB_CODE_SUCCESS) {
|
||||
SRowBuffPos* pPos = *(SRowBuffPos**)pNode->data;
|
||||
ASSERT(pPos->pRowBuff && pFileState->rowSize > 0);
|
||||
if (pPos->beFlushed) {
|
||||
if (pPos->beFlushed || !pPos->pRowBuff) {
|
||||
continue;
|
||||
}
|
||||
pPos->beFlushed = true;
|
||||
|
||||
qDebug("===stream===flushed start:%" PRId64, pFileState->getTs(pPos->pKey));
|
||||
if (streamStateGetBatchSize(batch) >= BATCH_LIMIT) {
|
||||
streamStatePutBatch_rocksdb(pFileState->pFileStore, batch);
|
||||
streamStateClearBatch(batch);
|
||||
}
|
||||
|
||||
SStateKey sKey = {.key = *((SWinKey*)pPos->pKey), .opNum = ((SStreamState*)pFileState->pFileStore)->number};
|
||||
code = streamStatePutBatchOptimize(pFileState->pFileStore, idx, batch, &sKey, pPos->pRowBuff, pFileState->rowSize,
|
||||
void* pSKey = pFileState->stateBuffCreateStateKeyFn(pPos, ((SStreamState*)pFileState->pFileStore)->number);
|
||||
code = streamStatePutBatchOptimize(pFileState->pFileStore, idx, batch, pSKey, pPos->pRowBuff, pFileState->rowSize,
|
||||
0, buf);
|
||||
taosMemoryFreeClear(pSKey);
|
||||
// todo handle failure
|
||||
memset(buf, 0, len);
|
||||
// qDebug("===stream===put %" PRId64 " to disc, res %d", sKey.key.ts, code);
|
||||
}
|
||||
taosMemoryFree(buf);
|
||||
|
||||
|
@ -487,6 +641,26 @@ int32_t deleteExpiredCheckPoint(SStreamFileState* pFileState, TSKEY mark) {
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t recoverSesssion(SStreamFileState* pFileState, int64_t ckId) {
|
||||
int code = TSDB_CODE_SUCCESS;
|
||||
SStreamStateCur* pCur = streamStateSessionSeekToLast_rocksdb(pFileState->pFileStore);
|
||||
if (pCur == NULL) {
|
||||
return -1;
|
||||
}
|
||||
while (code == TSDB_CODE_SUCCESS) {
|
||||
void* pVal = NULL;
|
||||
int32_t vlen = 0;
|
||||
SSessionKey key = {0};
|
||||
code = streamStateSessionGetKVByCur_rocksdb(pCur, &key, &pVal, &vlen);
|
||||
if (code != 0) {
|
||||
break;
|
||||
}
|
||||
taosMemoryFree(pVal);
|
||||
code = streamStateSessionCurPrev_rocksdb(pCur);
|
||||
}
|
||||
streamStateFreeCur(pCur);
|
||||
return code;
|
||||
}
|
||||
int32_t recoverSnapshot(SStreamFileState* pFileState, int64_t ckId) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (pFileState->maxTs != INT64_MIN) {
|
||||
|
@ -496,8 +670,7 @@ int32_t recoverSnapshot(SStreamFileState* pFileState, int64_t ckId) {
|
|||
deleteExpiredCheckPoint(pFileState, mark);
|
||||
}
|
||||
|
||||
SWinKey key = {.groupId = 0, .ts = 0};
|
||||
SStreamStateCur* pCur = streamStateSeekToLast_rocksdb(pFileState->pFileStore, &key);
|
||||
SStreamStateCur* pCur = streamStateSeekToLast_rocksdb(pFileState->pFileStore);
|
||||
if (pCur == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -507,9 +680,9 @@ int32_t recoverSnapshot(SStreamFileState* pFileState, int64_t ckId) {
|
|||
break;
|
||||
}
|
||||
void* pVal = NULL;
|
||||
int32_t pVLen = 0;
|
||||
SRowBuffPos* pNewPos = getNewRowPos(pFileState);
|
||||
code = streamStateGetKVByCur_rocksdb(pCur, pNewPos->pKey, (const void**)&pVal, &pVLen);
|
||||
int32_t vlen = 0;
|
||||
SRowBuffPos* pNewPos = getNewRowPosForWrite(pFileState);
|
||||
code = streamStateGetKVByCur_rocksdb(pCur, pNewPos->pKey, (const void**)&pVal, &vlen);
|
||||
if (code != TSDB_CODE_SUCCESS || pFileState->getTs(pNewPos->pKey) < pFileState->flushMark) {
|
||||
destroyRowBuffPos(pNewPos);
|
||||
SListNode* pNode = tdListPopTail(pFileState->usedBuffs);
|
||||
|
@ -517,16 +690,16 @@ int32_t recoverSnapshot(SStreamFileState* pFileState, int64_t ckId) {
|
|||
taosMemoryFreeClear(pVal);
|
||||
break;
|
||||
}
|
||||
ASSERT(pVLen == pFileState->rowSize);
|
||||
memcpy(pNewPos->pRowBuff, pVal, pVLen);
|
||||
ASSERT(vlen == pFileState->rowSize);
|
||||
memcpy(pNewPos->pRowBuff, pVal, vlen);
|
||||
taosMemoryFreeClear(pVal);
|
||||
pNewPos->beFlushed = true;
|
||||
code = tSimpleHashPut(pFileState->rowBuffMap, pNewPos->pKey, pFileState->keyLen, &pNewPos, POINTER_BYTES);
|
||||
code = tSimpleHashPut(pFileState->rowStateBuff, pNewPos->pKey, pFileState->keyLen, &pNewPos, POINTER_BYTES);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
destroyRowBuffPos(pNewPos);
|
||||
break;
|
||||
}
|
||||
code = streamStateCurPrev_rocksdb(pFileState->pFileStore, pCur);
|
||||
code = streamStateCurPrev_rocksdb(pCur);
|
||||
}
|
||||
streamStateFreeCur(pCur);
|
||||
|
||||
|
@ -539,3 +712,15 @@ void streamFileStateReloadInfo(SStreamFileState* pFileState, TSKEY ts) {
|
|||
pFileState->flushMark = TMAX(pFileState->flushMark, ts);
|
||||
pFileState->maxTs = TMAX(pFileState->maxTs, ts);
|
||||
}
|
||||
|
||||
void* getRowStateBuff(SStreamFileState* pFileState) { return pFileState->rowStateBuff; }
|
||||
|
||||
void* getStateFileStore(SStreamFileState* pFileState) { return pFileState->pFileStore; }
|
||||
|
||||
bool isDeteled(SStreamFileState* pFileState, TSKEY ts) {
|
||||
return pFileState->deleteMark > 0 && ts < (pFileState->maxTs - pFileState->deleteMark);
|
||||
}
|
||||
|
||||
bool isFlushedState(SStreamFileState* pFileState, TSKEY ts, TSKEY gap) { return ts <= (pFileState->flushMark + gap); }
|
||||
|
||||
int32_t getRowStateRowSize(SStreamFileState* pFileState) { return pFileState->rowSize; }
|
||||
|
|
|
@ -26,6 +26,10 @@ void tmsgSetDefault(const SMsgCb* msgcb) { defaultMsgCb = *msgcb; }
|
|||
int32_t tmsgPutToQueue(const SMsgCb* msgcb, EQueueType qtype, SRpcMsg* pMsg) {
|
||||
int32_t code = (*msgcb->putToQueueFp)(msgcb->mgmt, qtype, pMsg);
|
||||
if (code != 0) {
|
||||
SRpcMsg rsp = {.code = code, .info = pMsg->info};
|
||||
if (rsp.info.handle != NULL) {
|
||||
tmsgSendRsp(&rsp);
|
||||
}
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
pMsg->pCont = NULL;
|
||||
}
|
||||
|
|
|
@ -207,7 +207,8 @@
|
|||
,,n,system-test,python3 ./test.py -f 0-others/tag_index_basic.py
|
||||
,,n,system-test,python3 ./test.py -f 0-others/udfpy_main.py
|
||||
,,n,system-test,python3 ./test.py -N 3 -f 0-others/walRetention.py
|
||||
#,,n,system-test,python3 ./test.py -f 0-others/splitVGroup.py -N 5
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/splitVGroupRep1.py -N 3
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/splitVGroupRep3.py -N 3
|
||||
,,n,system-test,python3 ./test.py -f 0-others/timeRangeWise.py -N 3
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_database.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_replica.py -N 3
|
||||
|
|
|
@ -48,6 +48,7 @@ void createUsers(TAOS *taos, const char *host, char *qstr);
|
|||
void passVerTestMulti(const char *host, char *qstr);
|
||||
void sysInfoTest(TAOS *taos, const char *host, char *qstr);
|
||||
void userDroppedTest(TAOS *taos, const char *host, char *qstr);
|
||||
void clearTestEnv(TAOS *taos, const char *host, char *qstr);
|
||||
|
||||
int nPassVerNotified = 0;
|
||||
int nUserDropped = 0;
|
||||
|
@ -210,6 +211,7 @@ int main(int argc, char *argv[]) {
|
|||
passVerTestMulti(argv[1], qstr);
|
||||
sysInfoTest(taos, argv[1], qstr);
|
||||
userDroppedTest(taos, argv[1], qstr);
|
||||
clearTestEnv(taos, argv[1], qstr);
|
||||
|
||||
taos_close(taos);
|
||||
taos_cleanup();
|
||||
|
@ -267,9 +269,9 @@ void passVerTestMulti(const char *host, char *qstr) {
|
|||
queryDB(taos[0], "create database if not exists demo2 vgroups 1 minrows 10");
|
||||
queryDB(taos[0], "create database if not exists demo3 vgroups 1 minrows 10");
|
||||
|
||||
queryDB(taos[0], "create table demo1.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taos[0], "create table demo2.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taos[0], "create table demo3.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taos[0], "create table if not exists demo1.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taos[0], "create table if not exists demo2.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taos[0], "create table if not exists demo3.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
|
||||
strcpy(qstr, "alter user root pass 'taos'");
|
||||
queryDB(taos[0], qstr);
|
||||
|
@ -326,9 +328,9 @@ void sysInfoTest(TAOS *taosRoot, const char *host, char *qstr) {
|
|||
queryDB(taosRoot, "create database if not exists demo12 vgroups 1 minrows 10");
|
||||
queryDB(taosRoot, "create database if not exists demo13 vgroups 1 minrows 10");
|
||||
|
||||
queryDB(taosRoot, "create table demo11.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taosRoot, "create table demo12.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taosRoot, "create table demo13.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taosRoot, "create table if not exists demo11.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taosRoot, "create table if not exists demo12.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
queryDB(taosRoot, "create table if not exists demo13.stb (ts timestamp, c1 int) tags(t1 int)");
|
||||
|
||||
sprintf(qstr, "show grants");
|
||||
char output[BUF_LEN];
|
||||
|
@ -387,10 +389,14 @@ _REP:
|
|||
fprintf(stderr, ">>> succeed to run sysInfoTest\n");
|
||||
fprintf(stderr, "######## %s #########\n", __func__);
|
||||
}
|
||||
|
||||
static bool isDropUser = true;
|
||||
void userDroppedTest(TAOS *taos, const char *host, char *qstr) {
|
||||
// users
|
||||
int nTestUsers = nUser;
|
||||
int nLoop = 0;
|
||||
_loop:
|
||||
++nLoop;
|
||||
printf("\n\n%s:%d LOOP %d, nTestUsers:%d\n", __func__, __LINE__, nLoop, nTestUsers);
|
||||
for (int i = 0; i < nTestUsers; ++i) {
|
||||
// sprintf(users[i], "user%d", i);
|
||||
taosu[i] = taos_connect(host, users[i], "taos", NULL, 0);
|
||||
|
@ -426,7 +432,6 @@ void userDroppedTest(TAOS *taos, const char *host, char *qstr) {
|
|||
for (int i = 0; i < nTestUsers; ++i) {
|
||||
taos_close(taosu[i]);
|
||||
printf("%s:%d close taosu[%d]\n", __func__, __LINE__, i);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "######## %s #########\n", __func__);
|
||||
|
@ -437,5 +442,32 @@ void userDroppedTest(TAOS *taos, const char *host, char *qstr) {
|
|||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "######## %s #########\n", __func__);
|
||||
// sleep(300);
|
||||
|
||||
if (nLoop < 5) {
|
||||
nUserDropped = 0;
|
||||
for (int i = 0; i < nTestUsers; ++i) {
|
||||
sprintf(users[i], "user%d", i);
|
||||
sprintf(qstr, "CREATE USER %s PASS 'taos'", users[i]);
|
||||
fprintf(stderr, "%s:%d create user:%s\n", __func__, __LINE__, users[i]);
|
||||
queryDB(taos, qstr);
|
||||
}
|
||||
goto _loop;
|
||||
}
|
||||
isDropUser = false;
|
||||
}
|
||||
|
||||
void clearTestEnv(TAOS *taos, const char *host, char *qstr) {
|
||||
fprintf(stderr, "######## %s start #########\n", __func__);
|
||||
// restore password
|
||||
sprintf(qstr, "alter user root pass 'taosdata'");
|
||||
queryDB(taos, qstr);
|
||||
|
||||
if (isDropUser) {
|
||||
for (int i = 0; i < nUser; ++i) {
|
||||
sprintf(qstr, "drop user %s", users[i]);
|
||||
queryDB(taos, qstr);
|
||||
}
|
||||
}
|
||||
// sleep(3000);
|
||||
fprintf(stderr, "######## %s end #########\n", __func__);
|
||||
}
|
|
@ -17,7 +17,7 @@ $db = $dbPrefix . $i
|
|||
$mt = $mtPrefix . $i
|
||||
|
||||
sql drop database if exists $db
|
||||
sql create database $db duration 10 keep 20,20,20
|
||||
sql create database $db duration 3 keep 20,20,20
|
||||
sql use $db
|
||||
|
||||
sql_error alter database $db keep "20"
|
||||
|
@ -27,8 +27,8 @@ sql_error alter database $db keep 20.0
|
|||
sql_error alter database $db keep 20.0,20.0,20.0
|
||||
sql_error alter database $db keep 0,0,0
|
||||
sql_error alter database $db keep -1,-1,-1
|
||||
sql_error alter database $db keep 9,20
|
||||
sql_error alter database $db keep 9,9,9
|
||||
sql_error alter database $db keep 8,20
|
||||
sql_error alter database $db keep 8,9,9
|
||||
sql_error alter database $db keep 20,20,19
|
||||
sql_error alter database $db keep 20,19,20
|
||||
sql_error alter database $db keep 20,19,19
|
||||
|
|
|
@ -17,7 +17,7 @@ $db = $dbPrefix . $i
|
|||
$mt = $mtPrefix . $i
|
||||
|
||||
sql drop database if exists $db
|
||||
sql create database $db duration 10 keep 20
|
||||
sql create database $db duration 3 keep 20
|
||||
sql use $db
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
|
@ -36,7 +36,7 @@ sql_error alter database $db keep 0,0,0
|
|||
sql_error alter database $db keep 3
|
||||
sql_error alter database $db keep -1,-1,-1
|
||||
sql alter database $db keep 20,20
|
||||
sql_error alter database $db keep 9,9,9
|
||||
sql_error alter database $db keep 8,9,9
|
||||
sql_error alter database $db keep 20,20,19
|
||||
sql_error alter database $db keep 20,19,20
|
||||
sql_error alter database $db keep 20,19,19
|
||||
|
|
|
@ -150,26 +150,26 @@ sql_error create database $db keep 12,11,12
|
|||
sql_error create database $db keep 8
|
||||
sql_error create database $db keep 12,11
|
||||
sql_error create database $db keep 365001,365001,365001
|
||||
sql create database dbk0 keep 19
|
||||
sql create database dbk0 keep 39
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data27 != 27360m,27360m,27360m then
|
||||
if $data27 != 56160m,56160m,56160m then
|
||||
return -1
|
||||
endi
|
||||
sql drop database dbk0
|
||||
sql create database dbka keep 19,20
|
||||
sql create database dbka keep 39,40
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data27 != 27360m,28800m,28800m then
|
||||
if $data27 != 56160m,57600m,57600m then
|
||||
return -1
|
||||
endi
|
||||
sql drop database dbka
|
||||
|
||||
sql create database dbk1 keep 11,11,11
|
||||
sql create database dbk1 duration 3 keep 11,11,11
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
|
@ -178,7 +178,7 @@ if $data27 != 15840m,15840m,15840m then
|
|||
return -1
|
||||
endi
|
||||
sql drop database dbk1
|
||||
sql create database dbk2 keep 11,12,13
|
||||
sql create database dbk2 duration 3 keep 11,12,13
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
|
@ -187,7 +187,7 @@ if $data27 != 15840m,17280m,18720m then
|
|||
return -1
|
||||
endi
|
||||
sql drop database dbk2
|
||||
sql create database dbk3 keep 11,11,13
|
||||
sql create database dbk3 duration 3 keep 11,11,13
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
|
@ -196,7 +196,7 @@ if $data27 != 15840m,15840m,18720m then
|
|||
return -1
|
||||
endi
|
||||
sql drop database dbk3
|
||||
sql create database dbk4 keep 11,13,13
|
||||
sql create database dbk4 duration 3 keep 11,13,13
|
||||
sql select * from information_schema.ins_databases
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
|
|
|
@ -8,10 +8,12 @@ sleep 500
|
|||
|
||||
sql connect
|
||||
|
||||
print step1=============
|
||||
|
||||
sql create database test vgroups 1;
|
||||
sql use test;
|
||||
sql create table t1(ts timestamp, a int, b int , c int, d double);
|
||||
sql create stream streams1 trigger at_once into streamt as select _wstart, count(*) c1 from t1 interval(1s);
|
||||
sql create stream streams0 trigger at_once ignore expired 0 ignore update 0 into streamt as select _wstart, count(*) c1 from t1 interval(1s);
|
||||
|
||||
sql insert into t1 values(1648791211000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791212001,2,2,3,1.1);
|
||||
|
@ -71,13 +73,13 @@ if $rows != 29 then
|
|||
goto loop1
|
||||
endi
|
||||
|
||||
|
||||
print step2=============
|
||||
|
||||
sql create database test2 vgroups 10;
|
||||
sql use test2;
|
||||
sql create stable st(ts timestamp, a int, b int , c int, d double) tags(ta int,tb int,tc int);
|
||||
sql create table t1 using st tags(1,1,1);
|
||||
sql create stream streams2 trigger at_once ignore expired 0 waterMark 200s into streamt2 as select _wstart, count(*) c1 from t1 interval(1s);
|
||||
sql create stream streams2 trigger at_once ignore expired 0 ignore update 0 waterMark 200s into streamt2 as select _wstart, count(*) c1 from t1 interval(1s);
|
||||
|
||||
sql insert into t1 values(1648791211000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791212001,2,2,3,1.1);
|
||||
|
@ -137,4 +139,184 @@ if $rows != 29 then
|
|||
goto loop3
|
||||
endi
|
||||
|
||||
print step3=============
|
||||
|
||||
sql create database test1 vgroups 1;
|
||||
sql use test1;
|
||||
sql create table t1(ts timestamp, a int, b int , c int, d double);
|
||||
sql create stream streams1 trigger at_once ignore expired 0 ignore update 0 into streamt1 as select _wstart, count(*) c1 from t1 session(ts, 1s);
|
||||
|
||||
sql insert into t1 values(1648791211000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791213000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791215000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791217000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791219000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791221000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791223000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791225000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791227000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791229000,1,2,3,1.0);
|
||||
|
||||
sql insert into t1 values(1648791231000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791233000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791235000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791237000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791239000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791241000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791243000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791245000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791247000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791249000,1,2,3,1.0);
|
||||
|
||||
sql insert into t1 values(1648791251000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791253000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791255000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791257000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791259000,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791261000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791263000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791265000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791267000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791269000,1,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop4:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt1;
|
||||
sql select * from streamt1;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop4
|
||||
endi
|
||||
|
||||
sql insert into t1 values(1648791211001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791213001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791215001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791217001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791219001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791221001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791223001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791225001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791227001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791229001,1,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop5:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt1;
|
||||
sql select * from streamt1;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop5
|
||||
endi
|
||||
|
||||
if $data01 != 2 then
|
||||
print =====data01=$data01
|
||||
goto loop5
|
||||
endi
|
||||
|
||||
if $data91 != 2 then
|
||||
print =====data91=$data91
|
||||
goto loop5
|
||||
endi
|
||||
|
||||
sql insert into t1 values(1648791231001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791233001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791235001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791237001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791239001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791241001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791243001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791245001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791247001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791249001,1,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop6:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt1;
|
||||
sql select * from streamt1;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop6
|
||||
endi
|
||||
|
||||
if $data[10][1] != 2 then
|
||||
print =====data[10][1]=$data[10][1]
|
||||
goto loop6
|
||||
endi
|
||||
|
||||
if $data[19][1] != 2 then
|
||||
print =====data[19][1]=$data[19][1]
|
||||
goto loop6
|
||||
endi
|
||||
|
||||
sql insert into t1 values(1648791251001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791253001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791255001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791257001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791259001,1,2,3,1.1);
|
||||
sql insert into t1 values(1648791261001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791263001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791265001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791267001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791269001,1,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop7:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt1;
|
||||
sql select * from streamt1;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop7
|
||||
endi
|
||||
|
||||
if $data[20][1] != 2 then
|
||||
print =====[20][1]=$[20][1]
|
||||
goto loop7
|
||||
endi
|
||||
|
||||
if $data[29][1] != 2 then
|
||||
print =====[29][1]=$[29][1]
|
||||
goto loop7
|
||||
endi
|
||||
|
||||
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
|
@ -0,0 +1,217 @@
|
|||
system sh/stop_dnodes.sh
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/cfg.sh -n dnode1 -c debugflag -v 135
|
||||
system sh/cfg.sh -n dnode1 -c streamBufferSize -v 10
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
|
||||
sleep 500
|
||||
|
||||
sql connect
|
||||
|
||||
print step1=============
|
||||
|
||||
sql create database test3 vgroups 1;
|
||||
sql use test3;
|
||||
sql create table t1(ts timestamp, a int, b int , c int, d double);
|
||||
sql create stream streams3 trigger at_once ignore expired 0 ignore update 0 into streamt3 as select _wstart, count(*) c1 from t1 state_window(a);
|
||||
|
||||
sql insert into t1 values(1648791211000,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791213000,2,2,3,1.1);
|
||||
sql insert into t1 values(1648791215000,3,2,3,1.1);
|
||||
sql insert into t1 values(1648791217000,4,2,3,1.1);
|
||||
sql insert into t1 values(1648791219000,5,2,3,1.1);
|
||||
sql insert into t1 values(1648791221000,6,2,3,1.0);
|
||||
sql insert into t1 values(1648791223000,7,2,3,1.0);
|
||||
sql insert into t1 values(1648791225000,8,2,3,1.0);
|
||||
sql insert into t1 values(1648791227000,9,2,3,1.0);
|
||||
sql insert into t1 values(1648791229000,10,2,3,1.0);
|
||||
|
||||
sql insert into t1 values(1648791231000,11,2,3,1.0);
|
||||
sql insert into t1 values(1648791233000,12,2,3,1.1);
|
||||
sql insert into t1 values(1648791235000,13,2,3,1.1);
|
||||
sql insert into t1 values(1648791237000,14,2,3,1.1);
|
||||
sql insert into t1 values(1648791239000,15,2,3,1.1);
|
||||
sql insert into t1 values(1648791241000,16,2,3,1.0);
|
||||
sql insert into t1 values(1648791243000,17,2,3,1.0);
|
||||
sql insert into t1 values(1648791245000,18,2,3,1.0);
|
||||
sql insert into t1 values(1648791247000,19,2,3,1.0);
|
||||
sql insert into t1 values(1648791249000,20,2,3,1.0);
|
||||
|
||||
sql insert into t1 values(1648791251000,21,2,3,1.0);
|
||||
sql insert into t1 values(1648791253000,22,2,3,1.1);
|
||||
sql insert into t1 values(1648791255000,23,2,3,1.1);
|
||||
sql insert into t1 values(1648791257000,24,2,3,1.1);
|
||||
sql insert into t1 values(1648791259000,25,2,3,1.1);
|
||||
sql insert into t1 values(1648791261000,26,2,3,1.0);
|
||||
sql insert into t1 values(1648791263000,27,2,3,1.0);
|
||||
sql insert into t1 values(1648791265000,28,2,3,1.0);
|
||||
sql insert into t1 values(1648791267000,29,2,3,1.0);
|
||||
sql insert into t1 values(1648791269000,30,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop8:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt3;
|
||||
sql select * from streamt3;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop8
|
||||
endi
|
||||
|
||||
sql insert into t1 values(1648791211001,1,2,3,1.0);
|
||||
sql insert into t1 values(1648791213001,2,2,3,1.1);
|
||||
sql insert into t1 values(1648791215001,3,2,3,1.1);
|
||||
sql insert into t1 values(1648791217001,4,2,3,1.1);
|
||||
sql insert into t1 values(1648791219001,5,2,3,1.1);
|
||||
sql insert into t1 values(1648791221001,6,2,3,1.0);
|
||||
sql insert into t1 values(1648791223001,7,2,3,1.0);
|
||||
sql insert into t1 values(1648791225001,8,2,3,1.0);
|
||||
sql insert into t1 values(1648791227001,9,2,3,1.0);
|
||||
sql insert into t1 values(1648791229001,10,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop9:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt3;
|
||||
sql select * from streamt3;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop9
|
||||
endi
|
||||
|
||||
if $data01 != 2 then
|
||||
print =====data01=$data01
|
||||
goto loop9
|
||||
endi
|
||||
|
||||
if $data91 != 2 then
|
||||
print =====data91=$data91
|
||||
goto loop9
|
||||
endi
|
||||
|
||||
sql insert into t1 values(1648791231001,11,2,3,1.0);
|
||||
sql insert into t1 values(1648791233001,12,2,3,1.1);
|
||||
sql insert into t1 values(1648791235001,13,2,3,1.1);
|
||||
sql insert into t1 values(1648791237001,14,2,3,1.1);
|
||||
sql insert into t1 values(1648791239001,15,2,3,1.1);
|
||||
sql insert into t1 values(1648791241001,16,2,3,1.0);
|
||||
sql insert into t1 values(1648791243001,17,2,3,1.0);
|
||||
sql insert into t1 values(1648791245001,18,2,3,1.0);
|
||||
sql insert into t1 values(1648791247001,19,2,3,1.0);
|
||||
sql insert into t1 values(1648791249001,20,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop10:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt3;
|
||||
sql select * from streamt3;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop10
|
||||
endi
|
||||
|
||||
if $data[10][1] != 2 then
|
||||
print =====data[10][1]=$data[10][1]
|
||||
goto loop10
|
||||
endi
|
||||
|
||||
if $data[19][1] != 2 then
|
||||
print =====data[19][1]=$data[19][1]
|
||||
goto loop10
|
||||
endi
|
||||
|
||||
sql insert into t1 values(1648791251001,21,2,3,1.0);
|
||||
sql insert into t1 values(1648791253001,22,2,3,1.1);
|
||||
sql insert into t1 values(1648791255001,23,2,3,1.1);
|
||||
sql insert into t1 values(1648791257001,24,2,3,1.1);
|
||||
|
||||
#///////////////////////
|
||||
$loop_count = 0
|
||||
|
||||
loop11:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt3;
|
||||
sql select * from streamt3;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop11
|
||||
endi
|
||||
|
||||
if $data[20][1] != 2 then
|
||||
print =====[20][1]=$[20][1]
|
||||
goto loop11
|
||||
endi
|
||||
#///////////////////////
|
||||
|
||||
sql insert into t1 values(1648791259001,25,2,3,1.1);
|
||||
sql insert into t1 values(1648791261001,26,2,3,1.0);
|
||||
sql insert into t1 values(1648791263001,27,2,3,1.0);
|
||||
sql insert into t1 values(1648791265001,28,2,3,1.0);
|
||||
sql insert into t1 values(1648791267001,29,2,3,1.0);
|
||||
sql insert into t1 values(1648791269001,30,2,3,1.0);
|
||||
|
||||
$loop_count = 0
|
||||
|
||||
loop11:
|
||||
|
||||
sleep 200
|
||||
|
||||
$loop_count = $loop_count + 1
|
||||
if $loop_count == 10 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print 1 select * from streamt3;
|
||||
sql select * from streamt3;
|
||||
|
||||
if $rows != 30 then
|
||||
print =====rows=$rows
|
||||
goto loop11
|
||||
endi
|
||||
|
||||
if $data[20][1] != 2 then
|
||||
print =====[20][1]=$[20][1]
|
||||
goto loop11
|
||||
endi
|
||||
|
||||
if $data[29][1] != 2 then
|
||||
print =====[29][1]=$[29][1]
|
||||
goto loop11
|
||||
endi
|
||||
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
|
@ -132,85 +132,85 @@ sql select * from streamt order by s desc;
|
|||
|
||||
# row 0
|
||||
if $data01 != 2 then
|
||||
print ======$data01
|
||||
print =====data01=$data01
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data02 != 29 then
|
||||
print ======$data02
|
||||
print =====data02=$data02
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data03 != 7 then
|
||||
print ======$data03
|
||||
print =====data03=$data03
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data04 != 22 then
|
||||
print ======$data04
|
||||
print =====data04=$data04
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
# row 1
|
||||
if $data11 != 3 then
|
||||
print ======$data11
|
||||
print =====data11=$data11
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data12 != 33 then
|
||||
print ======$data12
|
||||
print =====data12=$data12
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data13 != 8 then
|
||||
print ======$data13
|
||||
print =====data13=$data13
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data14 != 21 then
|
||||
print ======$data14
|
||||
print =====data14=$data14
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
# row 2
|
||||
if $data21 != 4 then
|
||||
print ======$data21
|
||||
print =====data21=$data21
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data22 != 25 then
|
||||
print ======$data22
|
||||
print =====data22=$data22
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data23 != 2 then
|
||||
print ======$data23
|
||||
print =====data23=$data23
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data24 != 20 then
|
||||
print ======$data24
|
||||
print =====data24=$data24
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
# row 3
|
||||
if $data31 != 10 then
|
||||
print ======$data31
|
||||
print =====data31=$data31
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data32 != 54 then
|
||||
print ======$data32
|
||||
print =====data32=$data32
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data33 != 1 then
|
||||
print ======$data33
|
||||
print =====data33=$data33
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
if $data34 != 19 then
|
||||
print ======$data34
|
||||
print =====data34=$data34
|
||||
goto loop2
|
||||
endi
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ class TDTestCase:
|
|||
self.str510 = self.str255 + self.str255
|
||||
tdSql.error('alter dnode 1 "activeCode" "a"')
|
||||
tdSql.error('alter dnode 1 "activeCode" "' + self.str107 + '"')
|
||||
# tdSql.error('alter all dnodes "activeCode" "' + self.str108 + '"')
|
||||
tdSql.error('alter all dnodes "activeCode" "' + self.str108 + '"')
|
||||
tdSql.error('alter dnode 1 "activeCode" "' + self.str109 + '"')
|
||||
tdSql.error('alter all dnodes "activeCode" "' + self.str510 + '"')
|
||||
tdSql.query(f'select * from information_schema.ins_dnodes')
|
||||
|
@ -257,12 +257,12 @@ class TDTestCase:
|
|||
tdSql.error('alter all dnodes "cActiveCode" "' + self.str255 + '"')
|
||||
tdSql.error('alter all dnodes "cActiveCode" "' + self.str256 + '"')
|
||||
tdSql.error('alter all dnodes "cActiveCode" "' + self.str257 + '"')
|
||||
# tdSql.error('alter all dnodes "cActiveCode" "' + self.str254 + '"')
|
||||
tdSql.error('alter all dnodes "cActiveCode" "' + self.str254 + '"')
|
||||
tdSql.error('alter dnode 1 "cActiveCode" "' + self.str510 + '"')
|
||||
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],"")
|
||||
# tdSql.error('alter dnode 1 "cActiveCode" "' + self.str109 + '"')
|
||||
tdSql.error('alter dnode 1 "cActiveCode" "' + self.str109 + '"')
|
||||
tdSql.query(f'show dnodes')
|
||||
tdSql.checkEqual(tdSql.queryResult[0][9],"")
|
||||
tdSql.execute('alter all dnodes "cActiveCode" ""')
|
||||
|
|
|
@ -100,7 +100,7 @@ class TDTestCase:
|
|||
tdDnodes.deploy(1,cfg)
|
||||
tdDnodes.start(1)
|
||||
|
||||
tdSql.execute("create database test duration 1")
|
||||
tdSql.execute("create database test duration 8h")
|
||||
tdSql.execute("use test")
|
||||
|
||||
tdSql.execute("create table stb(ts timestamp, c int) tags(t int)")
|
||||
|
@ -117,7 +117,7 @@ class TDTestCase:
|
|||
tdLog.info("================= step3")
|
||||
tdSql.execute('drop database test')
|
||||
for i in range(10):
|
||||
tdSql.execute("create database test%d duration 1" %(i))
|
||||
tdSql.execute("create database test%d duration 8h" %(i))
|
||||
tdSql.execute("use test%d" %(i))
|
||||
tdSql.execute("create table tb (ts timestamp,i int)")
|
||||
for j in range(10):
|
||||
|
@ -216,7 +216,7 @@ class TDTestCase:
|
|||
tdDnodes.deploy(1,cfg)
|
||||
tdDnodes.start(1)
|
||||
|
||||
tdSql.execute('create database dbtest')
|
||||
tdSql.execute('create database dbtest duration 3')
|
||||
tdSql.execute('use dbtest')
|
||||
tdSql.execute('create table stb (ts timestamp,c0 int) tags(t0 int)')
|
||||
tdSql.execute('create table tb1 using stb tags(1)')
|
||||
|
|
|
@ -0,0 +1,440 @@
|
|||
###################################################################
|
||||
# Copyright (c) 2016 by TAOS Technologies, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is proprietary and confidential to TAOS Technologies.
|
||||
# No part of this file may be reproduced, stored, transmitted,
|
||||
# disclosed or used in any form or by any means other than as
|
||||
# expressly provided by the written permission from Jianhui Tao
|
||||
#
|
||||
###################################################################
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import random
|
||||
import time
|
||||
import copy
|
||||
import string
|
||||
|
||||
import taos
|
||||
from util.log import *
|
||||
from util.cases import *
|
||||
from util.sql import *
|
||||
|
||||
class TDTestCase:
|
||||
|
||||
# random string
|
||||
def random_string(self, count):
|
||||
letters = string.ascii_letters
|
||||
return ''.join(random.choice(letters) for i in range(count))
|
||||
|
||||
# get col value and total max min ...
|
||||
def getColsValue(self, i, j):
|
||||
# c1 value
|
||||
if random.randint(1, 10) == 5:
|
||||
c1 = None
|
||||
else:
|
||||
c1 = 1
|
||||
|
||||
# c2 value
|
||||
if j % 3200 == 0:
|
||||
c2 = 8764231
|
||||
elif random.randint(1, 10) == 5:
|
||||
c2 = None
|
||||
else:
|
||||
c2 = random.randint(-87654297, 98765321)
|
||||
|
||||
|
||||
value = f"({self.ts}, "
|
||||
|
||||
# c1
|
||||
if c1 is None:
|
||||
value += "null,"
|
||||
else:
|
||||
self.c1Cnt += 1
|
||||
value += f"{c1},"
|
||||
# c2
|
||||
if c2 is None:
|
||||
value += "null,"
|
||||
else:
|
||||
value += f"{c2},"
|
||||
# total count
|
||||
self.c2Cnt += 1
|
||||
# max
|
||||
if self.c2Max is None:
|
||||
self.c2Max = c2
|
||||
else:
|
||||
if c2 > self.c2Max:
|
||||
self.c2Max = c2
|
||||
# min
|
||||
if self.c2Min is None:
|
||||
self.c2Min = c2
|
||||
else:
|
||||
if c2 < self.c2Min:
|
||||
self.c2Min = c2
|
||||
# sum
|
||||
if self.c2Sum is None:
|
||||
self.c2Sum = c2
|
||||
else:
|
||||
self.c2Sum += c2
|
||||
|
||||
# c3 same with ts
|
||||
value += f"{self.ts})"
|
||||
|
||||
# move next
|
||||
self.ts += 1
|
||||
|
||||
return value
|
||||
|
||||
# insert data
|
||||
def insertData(self):
|
||||
tdLog.info("insert data ....")
|
||||
sqls = ""
|
||||
for i in range(self.childCnt):
|
||||
# insert child table
|
||||
values = ""
|
||||
pre_insert = f"insert into @db_name.t{i} values "
|
||||
for j in range(self.childRow):
|
||||
if values == "":
|
||||
values = self.getColsValue(i, j)
|
||||
else:
|
||||
values += "," + self.getColsValue(i, j)
|
||||
|
||||
# batch insert
|
||||
if j % self.batchSize == 0 and values != "":
|
||||
sql = pre_insert + values
|
||||
self.exeDouble(sql)
|
||||
values = ""
|
||||
# append last
|
||||
if values != "":
|
||||
sql = pre_insert + values
|
||||
self.exeDouble(sql)
|
||||
values = ""
|
||||
|
||||
# insert nomal talbe
|
||||
for i in range(20):
|
||||
self.ts += 1000
|
||||
name = self.random_string(20)
|
||||
sql = f"insert into @db_name.ta values({self.ts}, {i}, {self.ts%100000}, '{name}', false)"
|
||||
self.exeDouble(sql)
|
||||
|
||||
# insert finished
|
||||
tdLog.info(f"insert data successfully.\n"
|
||||
f" inserted child table = {self.childCnt}\n"
|
||||
f" inserted child rows = {self.childRow}\n"
|
||||
f" total inserted rows = {self.childCnt*self.childRow}\n")
|
||||
return
|
||||
|
||||
def exeDouble(self, sql):
|
||||
# dbname replace
|
||||
sql1 = sql.replace("@db_name", self.db1)
|
||||
|
||||
if len(sql1) > 100:
|
||||
tdLog.info(sql1[:100])
|
||||
else:
|
||||
tdLog.info(sql1)
|
||||
tdSql.execute(sql1)
|
||||
|
||||
sql2 = sql.replace("@db_name", self.db2)
|
||||
if len(sql2) > 100:
|
||||
tdLog.info(sql2[:100])
|
||||
else:
|
||||
tdLog.info(sql2)
|
||||
tdSql.execute(sql2)
|
||||
|
||||
|
||||
# prepareEnv
|
||||
def prepareEnv(self):
|
||||
# init
|
||||
self.ts = 1680000000000
|
||||
self.childCnt = 4
|
||||
self.childRow = 10000
|
||||
self.batchSize = 50000
|
||||
self.vgroups1 = 1
|
||||
self.vgroups2 = 1
|
||||
self.db1 = "db1"
|
||||
self.db2 = "db2"
|
||||
|
||||
# total
|
||||
self.c1Cnt = 0
|
||||
self.c2Cnt = 0
|
||||
self.c2Max = None
|
||||
self.c2Min = None
|
||||
self.c2Sum = None
|
||||
|
||||
# create database db
|
||||
sql = f"create database @db_name vgroups {self.vgroups1} replica 1"
|
||||
self.exeDouble(sql)
|
||||
|
||||
# create super talbe st
|
||||
sql = f"create table @db_name.st(ts timestamp, c1 int, c2 bigint, ts1 timestamp) tags(area int)"
|
||||
self.exeDouble(sql)
|
||||
|
||||
# create child table
|
||||
for i in range(self.childCnt):
|
||||
sql = f"create table @db_name.t{i} using @db_name.st tags({i}) "
|
||||
self.exeDouble(sql)
|
||||
|
||||
# create normal table
|
||||
sql = f"create table @db_name.ta(ts timestamp, c1 int, c2 bigint, c3 binary(32), c4 bool)"
|
||||
self.exeDouble(sql)
|
||||
|
||||
# insert data
|
||||
self.insertData()
|
||||
|
||||
# update
|
||||
self.ts = 1680000000000 + 20000
|
||||
self.childRow = 1000
|
||||
|
||||
|
||||
# delete data
|
||||
sql = "delete from @db_name.st where ts > 1680000019000 and ts < 1680000062000"
|
||||
self.exeDouble(sql)
|
||||
sql = "delete from @db_name.st where ts > 1680000099000 and ts < 1680000170000"
|
||||
self.exeDouble(sql)
|
||||
|
||||
# check data correct
|
||||
def checkExpect(self, sql, expectVal):
|
||||
tdSql.query(sql)
|
||||
rowCnt = tdSql.getRows()
|
||||
for i in range(rowCnt):
|
||||
val = tdSql.getData(i,0)
|
||||
if val != expectVal:
|
||||
tdLog.exit(f"Not expect . query={val} expect={expectVal} i={i} sql={sql}")
|
||||
return False
|
||||
|
||||
tdLog.info(f"check expect ok. sql={sql} expect ={expectVal} rowCnt={rowCnt}")
|
||||
return True
|
||||
|
||||
# init
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
seed = time.time() % 10000
|
||||
random.seed(seed)
|
||||
self.replicaVar = int(replicaVar)
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor(), True)
|
||||
|
||||
# check query result same
|
||||
def queryDouble(self, sql):
|
||||
# sql
|
||||
sql1 = sql.replace('@db_name', self.db1)
|
||||
tdLog.info(sql1)
|
||||
start1 = time.time()
|
||||
rows1 = tdSql.query(sql1)
|
||||
spend1 = time.time() - start1
|
||||
res1 = copy.copy(tdSql.queryResult)
|
||||
|
||||
sql2 = sql.replace('@db_name', self.db2)
|
||||
tdLog.info(sql2)
|
||||
start2 = time.time()
|
||||
tdSql.query(sql2)
|
||||
spend2 = time.time() - start2
|
||||
res2 = tdSql.queryResult
|
||||
|
||||
rowlen1 = len(res1)
|
||||
rowlen2 = len(res2)
|
||||
|
||||
if rowlen1 != rowlen2:
|
||||
tdLog.exit(f"both row count not equal. rowlen1={rowlen1} rowlen2={rowlen2} ")
|
||||
return False
|
||||
|
||||
for i in range(rowlen1):
|
||||
row1 = res1[i]
|
||||
row2 = res2[i]
|
||||
collen1 = len(row1)
|
||||
collen2 = len(row2)
|
||||
if collen1 != collen2:
|
||||
tdLog.exit(f"both col count not equal. collen1={collen1} collen2={collen2}")
|
||||
return False
|
||||
for j in range(collen1):
|
||||
if row1[j] != row2[j]:
|
||||
tdLog.exit(f"both col not equal. row={i} col={j} col1={row1[j]} col2={row2[j]} .")
|
||||
return False
|
||||
|
||||
# warning performance
|
||||
diff = (spend2 - spend1)*100/spend1
|
||||
tdLog.info("spend1=%.6fs spend2=%.6fs diff=%.1f%%"%(spend1, spend2, diff))
|
||||
if spend2 > spend1 and diff > 20:
|
||||
tdLog.info("warning: the diff for performance after spliting is over 20%")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# check result
|
||||
def checkResult(self):
|
||||
# check vgroupid
|
||||
sql = f"select vgroup_id from information_schema.ins_vgroups where db_name='{self.db2}'"
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.vgroups2)
|
||||
|
||||
# check child table count same
|
||||
sql = "select table_name from information_schema.ins_tables where db_name='@db_name' order by table_name"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# check row value is ok
|
||||
sql = "select * from @db_name.st order by ts"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# where
|
||||
sql = "select *,tbname from @db_name.st where c1 < 1000 order by ts"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# max
|
||||
sql = "select max(c1) from @db_name.st"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# min
|
||||
sql = "select min(c2) from @db_name.st"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# sum
|
||||
sql = "select sum(c1) from @db_name.st"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# normal table
|
||||
|
||||
# count
|
||||
sql = "select count(*) from @db_name.ta"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# all rows
|
||||
sql = "select * from @db_name.ta"
|
||||
self.queryDouble(sql)
|
||||
|
||||
# sum
|
||||
sql = "select sum(c1) from @db_name.ta"
|
||||
self.queryDouble(sql)
|
||||
|
||||
|
||||
# get vgroup list
|
||||
def getVGroup(self, db_name):
|
||||
vgidList = []
|
||||
sql = f"select vgroup_id from information_schema.ins_vgroups where db_name='{db_name}'"
|
||||
res = tdSql.getResult(sql)
|
||||
rows = len(res)
|
||||
for i in range(rows):
|
||||
vgidList.append(res[i][0])
|
||||
|
||||
return vgidList;
|
||||
|
||||
# split vgroup on db2
|
||||
def splitVGroup(self, db_name):
|
||||
vgids = self.getVGroup(db_name)
|
||||
selid = random.choice(vgids)
|
||||
sql = f"split vgroup {selid}"
|
||||
tdLog.info(sql)
|
||||
tdSql.execute(sql)
|
||||
|
||||
# wait end
|
||||
seconds = 300
|
||||
for i in range(seconds):
|
||||
sql ="show transactions;"
|
||||
rows = tdSql.query(sql)
|
||||
if rows == 0:
|
||||
tdLog.info("split vgroup finished.")
|
||||
return True
|
||||
#tdLog.info(f"i={i} wait split vgroup ...")
|
||||
time.sleep(1)
|
||||
|
||||
tdLog.exit(f"split vgroup transaction is not finished after executing {seconds}s")
|
||||
return False
|
||||
|
||||
# split error
|
||||
def expectSplitError(self, dbName):
|
||||
vgids = self.getVGroup(dbName)
|
||||
selid = random.choice(vgids)
|
||||
sql = f"split vgroup {selid}"
|
||||
tdLog.info(sql)
|
||||
tdSql.error(sql)
|
||||
|
||||
# expect split ok
|
||||
def expectSplitOk(self, dbName):
|
||||
# split vgroup
|
||||
vgList1 = self.getVGroup(dbName)
|
||||
self.splitVGroup(dbName)
|
||||
vgList2 = self.getVGroup(dbName)
|
||||
vgNum1 = len(vgList1) + 1
|
||||
vgNum2 = len(vgList2)
|
||||
if vgNum1 != vgNum2:
|
||||
tdLog.exit(f" vglist len={vgNum1} is not same for expect {vgNum2}")
|
||||
return
|
||||
|
||||
# split empty database
|
||||
def splitEmptyDB(self):
|
||||
dbName = "emptydb"
|
||||
vgNum = 2
|
||||
# create database
|
||||
sql = f"create database {dbName} vgroups {vgNum} replica 1"
|
||||
tdLog.info(sql)
|
||||
tdSql.execute(sql)
|
||||
|
||||
# split vgroup
|
||||
self.expectSplitOk(dbName)
|
||||
|
||||
|
||||
# forbid
|
||||
def checkForbid(self):
|
||||
# stream
|
||||
tdLog.info("check forbid split having stream...")
|
||||
tdSql.execute("create database streamdb;")
|
||||
tdSql.execute("use streamdb;")
|
||||
tdSql.execute("create table ta(ts timestamp, age int);")
|
||||
tdSql.execute("create stream ma into sta as select count(*) from ta interval(1s);")
|
||||
self.expectSplitError("streamdb")
|
||||
tdSql.execute("drop stream ma;")
|
||||
self.expectSplitOk("streamdb")
|
||||
|
||||
# topic
|
||||
tdLog.info("check forbid split having topic...")
|
||||
tdSql.execute("create database topicdb wal_retention_period 10;")
|
||||
tdSql.execute("use topicdb;")
|
||||
tdSql.execute("create table ta(ts timestamp, age int);")
|
||||
tdSql.execute("create topic toa as select * from ta;")
|
||||
|
||||
#self.expectSplitError("topicdb")
|
||||
tdSql.execute("drop topic toa;")
|
||||
self.expectSplitOk("topicdb")
|
||||
|
||||
# compact and check db2
|
||||
def compactAndCheck(self):
|
||||
tdLog.info("compact db2 and check result ...")
|
||||
# compact
|
||||
tdSql.execute(f"compact database {self.db2};")
|
||||
# check result
|
||||
self.checkResult()
|
||||
|
||||
# run
|
||||
def run(self):
|
||||
# prepare env
|
||||
self.prepareEnv()
|
||||
|
||||
for i in range(3):
|
||||
# split vgroup on db2
|
||||
start = time.time()
|
||||
self.splitVGroup(self.db2)
|
||||
end = time.time()
|
||||
self.vgroups2 += 1
|
||||
|
||||
# check two db query result same
|
||||
self.checkResult()
|
||||
spend = "%.3f"%(end-start)
|
||||
tdLog.info(f"split vgroup i={i} passed. spend = {spend}s")
|
||||
|
||||
# split empty db
|
||||
self.splitEmptyDB()
|
||||
|
||||
# check topic and stream forib
|
||||
self.checkForbid()
|
||||
|
||||
# compact database
|
||||
self.compactAndCheck()
|
||||
|
||||
# stop
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -137,10 +137,10 @@ class TDTestCase:
|
|||
tdSql.execute(sql1)
|
||||
|
||||
sql2 = sql.replace("@db_name", self.db2)
|
||||
if len(sql1) > 100:
|
||||
tdLog.info(sql1[:100])
|
||||
if len(sql2) > 100:
|
||||
tdLog.info(sql2[:100])
|
||||
else:
|
||||
tdLog.info(sql1)
|
||||
tdLog.info(sql2)
|
||||
tdSql.execute(sql2)
|
||||
|
||||
|
||||
|
@ -151,8 +151,8 @@ class TDTestCase:
|
|||
self.childCnt = 10
|
||||
self.childRow = 10000
|
||||
self.batchSize = 5000
|
||||
self.vgroups1 = 4
|
||||
self.vgroups2 = 4
|
||||
self.vgroups1 = 2
|
||||
self.vgroups2 = 2
|
||||
self.db1 = "db1"
|
||||
self.db2 = "db2"
|
||||
|
||||
|
@ -183,6 +183,16 @@ class TDTestCase:
|
|||
# insert data
|
||||
self.insertData()
|
||||
|
||||
# update
|
||||
self.ts = 1680000000000 + 10000
|
||||
self.childRow = 2000
|
||||
|
||||
# delete data
|
||||
sql = "delete from @db_name.st where ts > 1680000001900 and ts < 1680000012000"
|
||||
self.exeDouble(sql)
|
||||
sql = "delete from @db_name.st where ts > 1680000029000 and ts < 1680000048000"
|
||||
self.exeDouble(sql)
|
||||
|
||||
# check data correct
|
||||
def checkExpect(self, sql, expectVal):
|
||||
tdSql.query(sql)
|
||||
|
@ -225,7 +235,7 @@ class TDTestCase:
|
|||
rowlen2 = len(res2)
|
||||
|
||||
if rowlen1 != rowlen2:
|
||||
tdLog.exit(f"rowlen1={rowlen1} rowlen2={rowlen2} both not equal.")
|
||||
tdLog.exit(f"both row count not equal. rowlen1={rowlen1} rowlen2={rowlen2} ")
|
||||
return False
|
||||
|
||||
for i in range(rowlen1):
|
||||
|
@ -234,11 +244,11 @@ class TDTestCase:
|
|||
collen1 = len(row1)
|
||||
collen2 = len(row2)
|
||||
if collen1 != collen2:
|
||||
tdLog.exit(f"collen1={collen1} collen2={collen2} both not equal.")
|
||||
tdLog.exit(f"both col count not equal. collen1={collen1} collen2={collen2}")
|
||||
return False
|
||||
for j in range(collen1):
|
||||
if row1[j] != row2[j]:
|
||||
tdLog.exit(f"col={j} col1={row1[j]} col2={row2[j]} both col not equal.")
|
||||
tdLog.exit(f"both col not equal. row={i} col={j} col1={row1[j]} col2={row2[j]} .")
|
||||
return False
|
||||
|
||||
# warning performance
|
||||
|
@ -354,7 +364,7 @@ class TDTestCase:
|
|||
dbName = "emptydb"
|
||||
vgNum = 2
|
||||
# create database
|
||||
sql = f"create database {dbName} vgroups {vgNum}"
|
||||
sql = f"create database {dbName} vgroups {vgNum} replica 3"
|
||||
tdLog.info(sql)
|
||||
tdSql.execute(sql)
|
||||
|
||||
|
@ -380,7 +390,7 @@ class TDTestCase:
|
|||
tdSql.execute("use topicdb;")
|
||||
tdSql.execute("create table ta(ts timestamp, age int);")
|
||||
tdSql.execute("create topic toa as select * from ta;")
|
||||
self.expectSplitError("topicdb")
|
||||
#self.expectSplitError("topicdb")
|
||||
tdSql.execute("drop topic toa;")
|
||||
self.expectSplitOk("topicdb")
|
||||
|
||||
|
@ -397,7 +407,7 @@ class TDTestCase:
|
|||
# prepare env
|
||||
self.prepareEnv()
|
||||
|
||||
for i in range(5):
|
||||
for i in range(2):
|
||||
# split vgroup on db2
|
||||
start = time.time()
|
||||
self.splitVGroup(self.db2)
|
|
@ -15,7 +15,7 @@ class TDTestCase:
|
|||
self.stbname = "stb"
|
||||
self.ctbname = "ctb"
|
||||
self.keep_value = "2d,2d,2d"
|
||||
self.duration_value = "1d"
|
||||
self.duration_value = "16h"
|
||||
self.offset_time = 5
|
||||
self.sleep_time = self.offset_time*2
|
||||
|
||||
|
|
|
@ -141,12 +141,12 @@ class TDTestCase:
|
|||
def test_sort_for_partition_hint(self):
|
||||
sql = 'select count(*), c1 from meters partition by c1'
|
||||
sql_hint = 'select /*+ sort_for_group() */count(*), c1 from meters partition by c1'
|
||||
self.check_explain_res_has_row("Partition on", self.explain_sql(sql))
|
||||
#self.check_explain_res_has_row("Partition on", self.explain_sql(sql))
|
||||
self.check_explain_res_has_row("Sort", self.explain_sql(sql_hint))
|
||||
|
||||
sql = 'select count(*), c1, tbname from meters partition by tbname, c1'
|
||||
sql_hint = 'select /*+ sort_for_group() */ count(*), c1, tbname from meters partition by tbname, c1'
|
||||
self.check_explain_res_has_row("Partition on", self.explain_sql(sql))
|
||||
#self.check_explain_res_has_row("Partition on", self.explain_sql(sql))
|
||||
self.check_explain_res_has_row("Sort", self.explain_sql(sql_hint))
|
||||
|
||||
sql = 'select count(*), c1, tbname from meters partition by tbname, c1 interval(1s)'
|
||||
|
@ -156,7 +156,7 @@ class TDTestCase:
|
|||
|
||||
sql = 'select count(*), c1, t1 from meters partition by t1, c1'
|
||||
sql_hint = 'select /*+ sort_for_group() */ count(*), c1, t1 from meters partition by t1, c1'
|
||||
self.check_explain_res_has_row("Partition on", self.explain_sql(sql))
|
||||
#self.check_explain_res_has_row("Partition on", self.explain_sql(sql))
|
||||
self.check_explain_res_has_row("Sort", self.explain_sql(sql_hint))
|
||||
|
||||
sql = 'select count(*), c1, t1 from meters partition by t1, c1 interval(1s)'
|
||||
|
@ -208,7 +208,7 @@ class TDTestCase:
|
|||
sql_hint = self.add_order_by(self.add_hint(sql), order_by, select_list)
|
||||
sql = self.add_order_by(sql, order_by, select_list)
|
||||
self.check_explain_res_has_row("Sort", self.explain_sql(sql_hint))
|
||||
self.check_explain_res_has_row("Partition", self.explain_sql(sql))
|
||||
#self.check_explain_res_has_row("Partition", self.explain_sql(sql))
|
||||
self.query_and_compare_res(sql, sql_hint, compare_what=compare_what)
|
||||
|
||||
def test_sort_for_partition_res(self):
|
||||
|
|
|
@ -137,6 +137,10 @@ class TDTestCase:
|
|||
if not plan_found:
|
||||
tdLog.exit("plan: %s not found in res: [%s]" % (plan_str_expect, str(rows)))
|
||||
|
||||
def check_explain_res_no_row(self, plan_str_not_expect: str, res):
|
||||
for row in res:
|
||||
if str(row).find(plan_str_not_expect) >= 0:
|
||||
tdLog.exit('plan: [%s] found in: [%s]' % (plan_str_not_expect, str(row)))
|
||||
|
||||
def test_sort_for_partition_hint(self):
|
||||
pass
|
||||
|
@ -146,6 +150,9 @@ class TDTestCase:
|
|||
|
||||
def add_hint(self, sql: str) -> str:
|
||||
return "select /*+ sort_for_group() */ %s" % sql[6:]
|
||||
|
||||
def add_remove_partition_hint(self, sql: str) -> str:
|
||||
return "select /*+ remove_partition() */ %s" % sql[6:]
|
||||
|
||||
def query_with_time(self, sql):
|
||||
start = datetime.now()
|
||||
|
@ -200,8 +207,8 @@ class TDTestCase:
|
|||
def check_explain(self, sql):
|
||||
sql_hint = self.add_hint(sql)
|
||||
explain_res = self.explain_sql(sql)
|
||||
self.check_explain_res_has_row('SortMerge', explain_res)
|
||||
self.check_explain_res_has_row("blocking=0", explain_res)
|
||||
#self.check_explain_res_has_row('SortMerge', explain_res)
|
||||
#self.check_explain_res_has_row("blocking=0", explain_res)
|
||||
explain_res = self.explain_sql(sql_hint)
|
||||
self.check_explain_res_has_row('SortMerge', explain_res)
|
||||
self.check_explain_res_has_row('blocking=0', explain_res)
|
||||
|
@ -233,14 +240,27 @@ class TDTestCase:
|
|||
sql_hint = self.add_hint(sql)
|
||||
sql = self.add_order_by(sql, ele[3])
|
||||
sql_no_slimit = sql_template % (ele[0], ele[1], '')
|
||||
|
||||
sql_no_slimit = self.add_order_by(sql_no_slimit, ele[3])
|
||||
self.query_and_compare_first_rows(sql_hint, sql_no_slimit)
|
||||
|
||||
def test_remove_partition(self):
|
||||
sql = 'select c1, count(*) from meters partition by c1 slimit 10'
|
||||
explain_res = self.explain_sql(sql)
|
||||
self.check_explain_res_no_row("Partition", explain_res)
|
||||
self.check_explain_res_has_row("blocking=1", explain_res)
|
||||
|
||||
sql = 'select c1, count(*) from meters partition by c1,c2 slimit 10'
|
||||
explain_res = self.explain_sql(sql)
|
||||
self.check_explain_res_no_row("Partition", explain_res)
|
||||
self.check_explain_res_has_row("blocking=1", explain_res)
|
||||
|
||||
def run(self):
|
||||
self.prepareTestEnv()
|
||||
#time.sleep(99999999)
|
||||
self.test_pipelined_agg_plan_with_slimit()
|
||||
self.test_pipelined_agg_data_with_slimit()
|
||||
self.test_remove_partition()
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
|
|
|
@ -107,8 +107,8 @@ class RestoreBasic:
|
|||
status = True
|
||||
break
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
tdLog.info(f"sleep 500ms retry {i} to check status again...")
|
||||
time.sleep(1)
|
||||
tdLog.info(f"sleep 1s retry {i} to check status again...")
|
||||
|
||||
if status == False:
|
||||
tdLog.exit("check vgroups status failed, exit.")
|
||||
|
|
Loading…
Reference in New Issue