Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
0d54c5a3
T
TDengine
项目概览
taosdata
/
TDengine
大约 2 年 前同步成功
通知
1192
Star
22018
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
0d54c5a3
编写于
9月 26, 2022
作者:
Z
zhihaop
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: sql objects merging and sending are asynchronous
上级
e2a029ca
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
136 addition
and
98 deletion
+136
-98
src/client/inc/tscBatchWrite.h
src/client/inc/tscBatchWrite.h
+24
-11
src/client/src/tscBatchWrite.c
src/client/src/tscBatchWrite.c
+112
-87
未找到文件。
src/client/inc/tscBatchWrite.h
浏览文件 @
0d54c5a3
...
@@ -109,6 +109,14 @@ typedef struct SDispatcherTimeoutManager {
...
@@ -109,6 +109,14 @@ typedef struct SDispatcherTimeoutManager {
volatile
bool
shutdown
;
volatile
bool
shutdown
;
}
SDispatcherTimeoutManager
;
}
SDispatcherTimeoutManager
;
/**
* A batch that polls from SAsyncBatchWriteDispatcher::buffer.
*/
typedef
struct
SBatchRequest
{
size_t
nRequests
;
SSqlObj
*
pRequests
[];
}
SBatchRequest
;
/**
/**
* Create the dispatcher timeout manager.
* Create the dispatcher timeout manager.
*/
*/
...
@@ -135,20 +143,25 @@ void shutdownSDispatcherTimeoutManager(SDispatcherTimeoutManager* manager);
...
@@ -135,20 +143,25 @@ void shutdownSDispatcherTimeoutManager(SDispatcherTimeoutManager* manager);
/**
/**
* Merge SSqlObjs into single SSqlObj.
* Merge SSqlObjs into single SSqlObj.
*
*
* @param polls the array of SSqlObj*.
* @param pRequest the batch request.
* @param nPolls the number of SSqlObj* in the array.
* @param batch the batch SSqlObj*.
* @param batch the merged SSqlObj*.
* @return the status code.
* @return the merged SSqlObj.
*/
int32_t
dispatcherBatchBuilder
(
SBatchRequest
*
pRequest
,
SSqlObj
**
batch
);
/**
* Merge the sql statements and execute the merged sql statement asynchronously.
*
* @param pRequest the batch request. the request will be promised to free after calling this function.
*/
*/
int32_t
dispatcherBatchBuilder
(
SSqlObj
**
polls
,
size_t
nPolls
,
SSqlObj
**
batch
);
void
dispatcherAsyncExecute
(
SBatchRequest
*
pRequest
);
/**
/**
* Merge the sql statements and execute the merged sql statement.
* Merge the sql statements and execute the merged sql statement.
*
*
* @param polls the array of SSqlObj*.
* @param pRequest the batch request. you must call free(pRequest) after calling this function.
* @param nPolls the number of SSqlObj* in the array.
*/
*/
void
dispatcherExecute
(
S
SqlObj
**
polls
,
size_t
nPolls
);
void
dispatcherExecute
(
S
BatchRequest
*
pRequest
);
/**
/**
* Create the async batch write dispatcher.
* Create the async batch write dispatcher.
...
...
src/client/src/tscBatchWrite.c
浏览文件 @
0d54c5a3
...
@@ -17,9 +17,9 @@
...
@@ -17,9 +17,9 @@
#include "tscBatchMerge.h"
#include "tscBatchMerge.h"
#include "tscBatchWrite.h"
#include "tscBatchWrite.h"
#include "tscLog.h"
#include "tscSubquery.h"
#include "tscSubquery.h"
#include "tsclient.h"
#include "tsclient.h"
#include "tscLog.h"
/**
/**
* Represents the callback function and its context.
* Represents the callback function and its context.
...
@@ -57,9 +57,7 @@ inline static void tscReturnsError(SSqlObj* pSql, int code) {
...
@@ -57,9 +57,7 @@ inline static void tscReturnsError(SSqlObj* pSql, int code) {
}
}
pSql
->
res
.
code
=
code
;
pSql
->
res
.
code
=
code
;
if
(
pSql
->
fp
)
{
tscAsyncResultOnError
(
pSql
);
pSql
->
fp
(
pSql
->
param
,
pSql
,
code
);
}
}
}
/**
/**
...
@@ -104,47 +102,47 @@ static void batchResultCallback(void* param, TAOS_RES* tres, int32_t code) {
...
@@ -104,47 +102,47 @@ static void batchResultCallback(void* param, TAOS_RES* tres, int32_t code) {
free
(
context
);
free
(
context
);
}
}
int32_t
dispatcherBatchBuilder
(
S
SqlObj
**
polls
,
size_t
nPolls
,
SSqlObj
**
batch
)
{
int32_t
dispatcherBatchBuilder
(
S
BatchRequest
*
pRequest
,
SSqlObj
**
batch
)
{
if
(
!
polls
||
!
nPolls
)
{
assert
(
pRequest
);
return
TSDB_CODE_SUCCESS
;
assert
(
pRequest
->
pRequests
)
;
}
assert
(
pRequest
->
nRequests
);
// create the callback context.
// create the callback context.
SBatchCallbackContext
*
context
=
calloc
(
1
,
sizeof
(
SBatchCallbackContext
)
+
nPolls
*
sizeof
(
SCallbackHandler
));
SBatchCallbackContext
*
context
=
calloc
(
1
,
sizeof
(
SBatchCallbackContext
)
+
pRequest
->
nRequests
*
sizeof
(
SCallbackHandler
));
if
(
context
==
NULL
)
{
if
(
context
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
}
tscDebug
(
"create batch call back context: %p"
,
context
);
tscDebug
(
"create batch call back context: %p"
,
context
);
// initialize the callback context.
// initialize the callback context.
context
->
nHandlers
=
nPoll
s
;
context
->
nHandlers
=
pRequest
->
nRequest
s
;
for
(
size_t
i
=
0
;
i
<
nPoll
s
;
++
i
)
{
for
(
size_t
i
=
0
;
i
<
pRequest
->
nRequest
s
;
++
i
)
{
SSqlObj
*
pSql
=
p
oll
s
[
i
];
SSqlObj
*
pSql
=
p
Request
->
pRequest
s
[
i
];
context
->
handler
[
i
].
fp
=
pSql
->
fp
;
context
->
handler
[
i
].
fp
=
pSql
->
fp
;
context
->
handler
[
i
].
param
=
pSql
->
param
;
context
->
handler
[
i
].
param
=
pSql
->
param
;
}
}
// merge the statements into single one.
// merge the statements into single one.
tscDebug
(
"start to merge %zu sql objs"
,
nPoll
s
);
tscDebug
(
"start to merge %zu sql objs"
,
pRequest
->
nRequest
s
);
SSqlObj
*
pFirst
=
poll
s
[
0
];
SSqlObj
*
pFirst
=
pRequest
->
pRequest
s
[
0
];
int32_t
code
=
tscMergeSSqlObjs
(
polls
,
nPoll
s
,
pFirst
);
int32_t
code
=
tscMergeSSqlObjs
(
pRequest
->
pRequests
,
pRequest
->
nRequest
s
,
pFirst
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
const
char
*
msg
=
tstrerror
(
code
);
const
char
*
msg
=
tstrerror
(
code
);
tscDebug
(
"failed to merge sql objects: %s"
,
msg
);
tscDebug
(
"failed to merge sql objects: %s"
,
msg
);
free
(
context
);
free
(
context
);
taosReleaseRef
(
tscObjRef
,
pFirst
->
self
);
return
code
;
return
code
;
}
}
pFirst
->
fp
=
batchResultCallback
;
pFirst
->
fp
=
batchResultCallback
;
pFirst
->
param
=
context
;
pFirst
->
param
=
context
;
pFirst
->
fetchFp
=
pFirst
->
fp
;
pFirst
->
fetchFp
=
pFirst
->
fp
;
taosAcquireRef
(
tscObjRef
,
pFirst
->
self
);
*
batch
=
pFirst
;
*
batch
=
pFirst
;
for
(
int
i
=
1
;
i
<
nPoll
s
;
++
i
)
{
for
(
int
i
=
0
;
i
<
pRequest
->
nRequest
s
;
++
i
)
{
SSqlObj
*
pSql
=
poll
s
[
i
];
SSqlObj
*
pSql
=
pRequest
->
pRequest
s
[
i
];
taosReleaseRef
(
tscObjRef
,
pSql
->
self
);
taosReleaseRef
(
tscObjRef
,
pSql
->
self
);
}
}
return
code
;
return
code
;
...
@@ -158,40 +156,37 @@ int32_t dispatcherBatchBuilder(SSqlObj** polls, size_t nPolls, SSqlObj** batch)
...
@@ -158,40 +156,37 @@ int32_t dispatcherBatchBuilder(SSqlObj** polls, size_t nPolls, SSqlObj** batch)
* @param nPolls the number of polled SSqlObj*.
* @param nPolls the number of polled SSqlObj*.
* @return all the SSqlObj* in the buffer.
* @return all the SSqlObj* in the buffer.
*/
*/
inline
static
S
SqlObj
**
dispatcherPollAll
(
SAsyncBatchWriteDispatcher
*
dispatcher
,
size_t
*
nPolls
)
{
inline
static
S
BatchRequest
*
dispatcherPollAll
(
SAsyncBatchWriteDispatcher
*
dispatcher
)
{
if
(
!
dispatcher
->
bufferSize
)
{
if
(
!
dispatcher
->
bufferSize
)
{
*
nPolls
=
0
;
return
NULL
;
return
NULL
;
}
}
S
SqlObj
**
clone
=
malloc
(
sizeof
(
SSqlObj
*
)
*
dispatcher
->
bufferSize
);
S
BatchRequest
*
pRequest
=
malloc
(
sizeof
(
SBatchRequest
)
+
sizeof
(
SSqlObj
*
)
*
dispatcher
->
bufferSize
);
if
(
clone
==
NULL
)
{
if
(
pRequest
==
NULL
)
{
tscError
(
"failed to poll all items: out of memory"
);
tscError
(
"failed to poll all items: out of memory"
);
*
nPolls
=
0
;
return
NULL
;
return
NULL
;
}
}
memcpy
(
clone
,
dispatcher
->
buffer
,
sizeof
(
SSqlObj
*
)
*
dispatcher
->
bufferSize
);
*
nPolls
=
dispatcher
->
bufferSize
;
memcpy
(
pRequest
->
pRequests
,
dispatcher
->
buffer
,
sizeof
(
SSqlObj
*
)
*
dispatcher
->
bufferSize
);
pRequest
->
nRequests
=
dispatcher
->
bufferSize
;
dispatcher
->
currentSize
=
0
;
dispatcher
->
currentSize
=
0
;
dispatcher
->
bufferSize
=
0
;
dispatcher
->
bufferSize
=
0
;
return
clone
;
return
pRequest
;
}
}
/**
/**
* Poll all the SSqlObj* in the dispatcher's buffer.
* Poll all the SSqlObj* in the dispatcher's buffer.
*
*
* @param dispatcher the dispatcher.
* @param dispatcher the dispatcher.
* @param nPolls the number of polled SSqlObj*.
* @return all the SSqlObj* in the buffer.
* @return all the SSqlObj* in the buffer.
*/
*/
inline
static
S
SqlObj
**
dispatcherLockPollAll
(
SAsyncBatchWriteDispatcher
*
dispatcher
,
size_t
*
nPolls
)
{
inline
static
S
BatchRequest
*
dispatcherLockPollAll
(
SAsyncBatchWriteDispatcher
*
dispatcher
)
{
S
SqlObj
**
polls
=
NULL
;
S
BatchRequest
*
pRequest
=
NULL
;
pthread_mutex_lock
(
&
dispatcher
->
bufferMutex
);
pthread_mutex_lock
(
&
dispatcher
->
bufferMutex
);
p
olls
=
dispatcherPollAll
(
dispatcher
,
nPolls
);
p
Request
=
dispatcherPollAll
(
dispatcher
);
pthread_cond_broadcast
(
&
dispatcher
->
notFull
);
pthread_cond_broadcast
(
&
dispatcher
->
notFull
);
pthread_mutex_unlock
(
&
dispatcher
->
bufferMutex
);
pthread_mutex_unlock
(
&
dispatcher
->
bufferMutex
);
return
p
olls
;
return
p
Request
;
}
}
/**
/**
...
@@ -229,41 +224,42 @@ inline static bool dispatcherTryOffer(SAsyncBatchWriteDispatcher* dispatcher, SS
...
@@ -229,41 +224,42 @@ inline static bool dispatcherTryOffer(SAsyncBatchWriteDispatcher* dispatcher, SS
}
}
// the dispatcher reaches batch size.
// the dispatcher reaches batch size.
size_t
nPolls
=
0
;
SBatchRequest
*
pRequest
=
dispatcherPollAll
(
dispatcher
);
SSqlObj
**
polls
=
dispatcherPollAll
(
dispatcher
,
&
nPolls
);
pthread_cond_broadcast
(
&
dispatcher
->
notFull
);
pthread_cond_broadcast
(
&
dispatcher
->
notFull
);
pthread_mutex_unlock
(
&
dispatcher
->
bufferMutex
);
pthread_mutex_unlock
(
&
dispatcher
->
bufferMutex
);
if
(
polls
)
{
if
(
pRequest
)
{
dispatcherExecute
(
polls
,
nPolls
);
dispatcherAsyncExecute
(
pRequest
);
free
(
polls
);
}
}
return
true
;
return
true
;
}
}
void
dispatcherExecute
(
S
SqlObj
**
polls
,
size_t
nPolls
)
{
void
dispatcherExecute
(
S
BatchRequest
*
pRequest
)
{
int32_t
code
=
TSDB_CODE_SUCCESS
;
int32_t
code
=
TSDB_CODE_SUCCESS
;
// no item in the buffer (items has been taken by other threads).
// no item in the buffer (items has been taken by other threads).
if
(
!
p
olls
||
!
nPolls
)
{
if
(
!
p
Request
)
{
return
;
return
;
}
}
assert
(
pRequest
->
pRequests
);
assert
(
pRequest
->
nRequests
);
// merge the statements into single one.
// merge the statements into single one.
SSqlObj
*
merged
=
NULL
;
SSqlObj
*
pSql
=
NULL
;
code
=
dispatcherBatchBuilder
(
p
olls
,
nPolls
,
&
merged
);
code
=
dispatcherBatchBuilder
(
p
Request
,
&
pSql
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
goto
_error
;
goto
_error
;
}
}
tscDebug
(
"merging %zu sql objs into %p"
,
nPolls
,
merged
);
tscDebug
(
"merging %zu sql objs into %p"
,
pRequest
->
nRequests
,
pSql
);
tscHandleMultivnodeInsert
(
merged
);
tscHandleMultivnodeInsert
(
pSql
);
return
;
return
;
_error:
_error:
tscError
(
"send async batch sql obj failed, reason: %s"
,
tstrerror
(
code
));
tscError
(
"send async batch sql obj failed, reason: %s"
,
tstrerror
(
code
));
// handling the failures.
// handling the failures.
for
(
size_t
i
=
0
;
i
<
nPoll
s
;
++
i
)
{
for
(
size_t
i
=
0
;
i
<
pRequest
->
nRequest
s
;
++
i
)
{
SSqlObj
*
item
=
p
oll
s
[
i
];
SSqlObj
*
item
=
p
Request
->
pRequest
s
[
i
];
tscReturnsError
(
item
,
code
);
tscReturnsError
(
item
,
code
);
}
}
}
}
...
@@ -275,7 +271,7 @@ _error:
...
@@ -275,7 +271,7 @@ _error:
* @param millis the duration in milliseconds.
* @param millis the duration in milliseconds.
* @return the timespec after `millis` ms.
* @return the timespec after `millis` ms.
*/
*/
static
inline
void
afterMillis
(
struct
timespec
*
t
,
int32_t
millis
)
{
static
inline
void
afterMillis
(
struct
timespec
*
t
,
int32_t
millis
)
{
t
->
tv_nsec
+=
millis
*
1000000L
;
t
->
tv_nsec
+=
millis
*
1000000L
;
t
->
tv_sec
+=
t
->
tv_nsec
/
1000000000L
;
t
->
tv_sec
+=
t
->
tv_nsec
/
1000000000L
;
t
->
tv_nsec
%=
1000000000L
;
t
->
tv_nsec
%=
1000000000L
;
...
@@ -314,12 +310,9 @@ static void* timeoutManagerCallback(void* arg) {
...
@@ -314,12 +310,9 @@ static void* timeoutManagerCallback(void* arg) {
clock_gettime
(
CLOCK_REALTIME
,
&
timeout
);
clock_gettime
(
CLOCK_REALTIME
,
&
timeout
);
afterMillis
(
&
timeout
,
manager
->
timeoutMs
);
afterMillis
(
&
timeout
,
manager
->
timeoutMs
);
size_t
nPolls
=
0
;
SBatchRequest
*
pRequest
=
dispatcherLockPollAll
(
manager
->
dispatcher
);
SSqlObj
**
polls
=
dispatcherLockPollAll
(
manager
->
dispatcher
,
&
nPolls
);
if
(
pRequest
)
{
dispatcherAsyncExecute
(
pRequest
);
if
(
polls
)
{
dispatcherExecute
(
polls
,
nPolls
);
free
(
polls
);
}
}
// Similar to scheduleAtFixedRate in Java, if the execution time exceed
// Similar to scheduleAtFixedRate in Java, if the execution time exceed
...
@@ -380,13 +373,12 @@ void destroySAsyncBatchWriteDispatcher(SAsyncBatchWriteDispatcher* dispatcher) {
...
@@ -380,13 +373,12 @@ void destroySAsyncBatchWriteDispatcher(SAsyncBatchWriteDispatcher* dispatcher) {
// poll and send all the statements in the buffer.
// poll and send all the statements in the buffer.
while
(
true
)
{
while
(
true
)
{
size_t
nPolls
=
0
;
SBatchRequest
*
pRequest
=
dispatcherLockPollAll
(
dispatcher
);
SSqlObj
**
polls
=
dispatcherLockPollAll
(
dispatcher
,
&
nPolls
);
if
(
!
pRequest
)
{
if
(
!
polls
)
{
break
;
break
;
}
}
dispatcherExecute
(
p
olls
,
nPolls
);
dispatcherExecute
(
p
Request
);
free
(
p
olls
);
free
(
p
Request
);
}
}
// destroy the timeout manager.
// destroy the timeout manager.
destroySDispatcherTimeoutManager
(
dispatcher
->
timeoutManager
);
destroySDispatcherTimeoutManager
(
dispatcher
->
timeoutManager
);
...
@@ -463,7 +455,8 @@ static void destroyDispatcher(void* arg) {
...
@@ -463,7 +455,8 @@ static void destroyDispatcher(void* arg) {
destroySAsyncBatchWriteDispatcher
(
dispatcher
);
destroySAsyncBatchWriteDispatcher
(
dispatcher
);
}
}
SDispatcherManager
*
createDispatcherManager
(
STscObj
*
pClient
,
int32_t
batchSize
,
int32_t
timeoutMs
,
bool
isThreadLocal
)
{
SDispatcherManager
*
createDispatcherManager
(
STscObj
*
pClient
,
int32_t
batchSize
,
int32_t
timeoutMs
,
bool
isThreadLocal
)
{
SDispatcherManager
*
dispatcher
=
calloc
(
1
,
sizeof
(
SDispatcherManager
));
SDispatcherManager
*
dispatcher
=
calloc
(
1
,
sizeof
(
SDispatcherManager
));
if
(
!
dispatcher
)
{
if
(
!
dispatcher
)
{
return
NULL
;
return
NULL
;
...
@@ -576,3 +569,35 @@ bool isShutdownSDispatcherTimeoutManager(SDispatcherTimeoutManager* manager) {
...
@@ -576,3 +569,35 @@ bool isShutdownSDispatcherTimeoutManager(SDispatcherTimeoutManager* manager) {
}
}
return
atomic_load_8
(
&
manager
->
shutdown
);
return
atomic_load_8
(
&
manager
->
shutdown
);
}
}
/**
* The proxy function to call `dispatcherExecute`.
*
* @param pMsg the schedule message.
*/
static
void
dispatcherExecuteProxy
(
struct
SSchedMsg
*
pMsg
)
{
SBatchRequest
*
pRequest
=
pMsg
->
ahandle
;
if
(
!
pRequest
)
{
return
;
}
pMsg
->
ahandle
=
NULL
;
dispatcherExecute
(
pRequest
);
free
(
pRequest
);
}
void
dispatcherAsyncExecute
(
SBatchRequest
*
pRequest
)
{
if
(
!
pRequest
)
{
return
;
}
assert
(
pRequest
->
pRequests
);
assert
(
pRequest
->
nRequests
);
SSchedMsg
schedMsg
=
{
0
};
schedMsg
.
fp
=
dispatcherExecuteProxy
;
schedMsg
.
ahandle
=
(
void
*
)
pRequest
;
schedMsg
.
thandle
=
(
void
*
)
1
;
schedMsg
.
msg
=
0
;
taosScheduleTask
(
tscQhandle
,
&
schedMsg
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录