Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
5e3e0485
TDengine
项目概览
taosdata
/
TDengine
大约 1 年 前同步成功
通知
1184
Star
22015
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5e3e0485
编写于
2月 24, 2022
作者:
S
Shengliang Guan
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
config
上级
d15e60d1
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
44 addition
and
75 deletion
+44
-75
include/dnode/mgmt/dnode.h
include/dnode/mgmt/dnode.h
+1
-17
source/common/src/tglobal.c
source/common/src/tglobal.c
+18
-10
source/dnode/mgmt/daemon/inc/dmnInt.h
source/dnode/mgmt/daemon/inc/dmnInt.h
+0
-1
source/dnode/mgmt/daemon/src/dmnCfg.c
source/dnode/mgmt/daemon/src/dmnCfg.c
+0
-12
source/dnode/mgmt/daemon/src/dmnMain.c
source/dnode/mgmt/daemon/src/dmnMain.c
+6
-8
source/dnode/mgmt/impl/inc/dndEnv.h
source/dnode/mgmt/impl/inc/dndEnv.h
+0
-6
source/dnode/mgmt/impl/src/dndBnode.c
source/dnode/mgmt/impl/src/dndBnode.c
+1
-1
source/dnode/mgmt/impl/src/dndEnv.c
source/dnode/mgmt/impl/src/dndEnv.c
+6
-8
source/dnode/mgmt/impl/src/dndMgmt.c
source/dnode/mgmt/impl/src/dndMgmt.c
+2
-2
source/dnode/mgmt/impl/src/dndMnode.c
source/dnode/mgmt/impl/src/dndMnode.c
+2
-2
source/dnode/mgmt/impl/src/dndQnode.c
source/dnode/mgmt/impl/src/dndQnode.c
+1
-1
source/dnode/mgmt/impl/src/dndSnode.c
source/dnode/mgmt/impl/src/dndSnode.c
+1
-1
source/dnode/mgmt/impl/src/dndTransport.c
source/dnode/mgmt/impl/src/dndTransport.c
+1
-1
source/dnode/mgmt/impl/src/dndVnodes.c
source/dnode/mgmt/impl/src/dndVnodes.c
+5
-5
未找到文件。
include/dnode/mgmt/dnode.h
浏览文件 @
5e3e0485
...
...
@@ -25,22 +25,12 @@ extern "C" {
/* ------------------------ TYPES EXPOSED ---------------- */
typedef
struct
SDnode
SDnode
;
/* ------------------------ Environment ------------------ */
typedef
struct
{
int32_t
sver
;
int32_t
numOfCores
;
uint16_t
numOfCommitThreads
;
bool
enableTelem
;
bool
printAuth
;
}
SDnodeEnvCfg
;
/**
* @brief Initialize the environment
*
* @param pOption Option of the environment
* @return int32_t 0 for success and -1 for failure
*/
int32_t
dndInit
(
const
SDnodeEnvCfg
*
pCfg
);
int32_t
dndInit
();
/**
* @brief clear the environment
...
...
@@ -51,12 +41,6 @@ void dndCleanup();
/* ------------------------ SDnode ----------------------- */
typedef
struct
{
int32_t
numOfSupportVnodes
;
// int32_t statusInterval;
// float numOfThreadsPerCore;
// float ratioOfQueryCores;
// int32_t maxShellConns;
// int32_t shellActivityTimer;
uint16_t
serverPort
;
char
dataDir
[
TSDB_FILENAME_LEN
];
char
localEp
[
TSDB_EP_LEN
];
...
...
source/common/src/tglobal.c
浏览文件 @
5e3e0485
...
...
@@ -220,7 +220,6 @@ static void taosAddClientLogCfg(SConfig *pCfg) {
}
static
void
taosAddServerLogCfg
(
SConfig
*
pCfg
)
{
taosAddClientLogCfg
(
pCfg
);
cfgAddInt32
(
pCfg
,
"dDebugFlag"
,
dDebugFlag
,
0
,
255
,
0
);
cfgAddInt32
(
pCfg
,
"vDebugFlag"
,
vDebugFlag
,
0
,
255
,
0
);
cfgAddInt32
(
pCfg
,
"mDebugFlag"
,
mDebugFlag
,
0
,
255
,
0
);
...
...
@@ -277,7 +276,6 @@ static void taosAddClientCfg(SConfig *pCfg) {
}
static
void
taosAddServerCfg
(
SConfig
*
pCfg
)
{
taosAddClientCfg
(
pCfg
);
cfgAddInt32
(
pCfg
,
"supportVnodes"
,
256
,
0
,
65536
,
0
);
cfgAddDir
(
pCfg
,
"dataDir"
,
osDataDir
(),
0
);
cfgAddFloat
(
pCfg
,
"minimalDataDirGB"
,
2
.
0
f
,
0
.
001
f
,
10000000
,
0
);
...
...
@@ -324,7 +322,6 @@ static void taosSetServerLogCfg(SConfig *pCfg) {
tsdbDebugFlag
=
cfgGetItem
(
pCfg
,
"tsdbDebugFlag"
)
->
i32
;
tqDebugFlag
=
cfgGetItem
(
pCfg
,
"tqDebugFlag"
)
->
i32
;
fsDebugFlag
=
cfgGetItem
(
pCfg
,
"fsDebugFlag"
)
->
i32
;
taosSetAllDebugFlag
(
cfgGetItem
(
pCfg
,
"debugFlag"
)
->
i32
);
}
static
void
taosSetClientCfg
(
SConfig
*
pCfg
)
{
...
...
@@ -342,12 +339,15 @@ static void taosSetClientCfg(SConfig *pCfg) {
cfgSetItem
(
pCfg
,
"timezone"
,
osTimezone
(),
pItem
->
stype
);
taosGetSystemInfo
();
if
(
tsNumOfCores
<=
0
)
{
tsNumOfCores
=
1
;
if
(
tsNumOfCores
<=
1
)
{
tsNumOfCores
=
2
;
}
bool
enableCore
=
cfgGetItem
(
pCfg
,
"enableCoreFile"
)
->
bval
;
taosSetCoreDump
(
enableCore
);
// todo
tsVersion
=
30000000
;
}
static
void
taosSetServerCfg
(
SConfig
*
pCfg
)
{
...
...
@@ -363,15 +363,16 @@ static void taosSetServerCfg(SConfig *pCfg) {
int32_t
taosCreateLog
(
const
char
*
logname
,
int32_t
logFileNum
,
const
char
*
cfgDir
,
const
char
*
envFile
,
const
char
*
apolloUrl
,
bool
tsc
)
{
SConfig
*
pCfg
=
cfgInit
();
if
(
ts
Cfg
==
NULL
)
return
-
1
;
if
(
p
Cfg
==
NULL
)
return
-
1
;
if
(
tsc
)
{
taosAddClientLogCfg
(
pCfg
);
}
else
{
taosAddClientLogCfg
(
pCfg
);
taosAddServerLogCfg
(
pCfg
);
}
if
(
taosLoadCfg
(
ts
Cfg
,
cfgDir
,
envFile
,
apolloUrl
)
!=
0
)
{
if
(
taosLoadCfg
(
p
Cfg
,
cfgDir
,
envFile
,
apolloUrl
)
!=
0
)
{
uError
(
"failed to load cfg since %s"
,
terrstr
());
cfgCleanup
(
pCfg
);
return
-
1
;
...
...
@@ -379,8 +380,11 @@ int32_t taosCreateLog(const char *logname, int32_t logFileNum, const char *cfgDi
if
(
tsc
)
{
taosSetClientLogCfg
(
pCfg
);
taosSetAllDebugFlag
(
cfgGetItem
(
pCfg
,
"debugFlag"
)
->
i32
);
}
else
{
taosSetClientLogCfg
(
pCfg
);
taosSetServerLogCfg
(
pCfg
);
taosSetAllDebugFlag
(
cfgGetItem
(
pCfg
,
"debugFlag"
)
->
i32
);
}
if
(
taosInitLog
(
logname
,
logFileNum
)
!=
0
)
{
...
...
@@ -396,12 +400,15 @@ int32_t taosCreateLog(const char *logname, int32_t logFileNum, const char *cfgDi
int32_t
taosInitCfg
(
const
char
*
cfgDir
,
const
char
*
envFile
,
const
char
*
apolloUrl
,
bool
tsc
)
{
if
(
tsCfg
!=
NULL
)
return
0
;
tsCfg
=
cfgInit
();
if
(
tsCfg
==
NULL
)
return
-
1
;
if
(
tsc
)
{
taosAddServerCfg
(
tsCfg
);
taosAddClientLogCfg
(
tsCfg
);
taosAddClientCfg
(
tsCfg
);
}
else
{
taosAddClientLogCfg
(
tsCfg
);
taosAddServerLogCfg
(
tsCfg
);
taosAddClientCfg
(
tsCfg
);
taosAddServerCfg
(
tsCfg
);
}
if
(
taosLoadCfg
(
tsCfg
,
cfgDir
,
envFile
,
apolloUrl
)
!=
0
)
{
...
...
@@ -414,6 +421,7 @@ int32_t taosInitCfg(const char *cfgDir, const char *envFile, const char *apolloU
if
(
tsc
)
{
taosSetClientCfg
(
tsCfg
);
}
else
{
taosSetClientCfg
(
tsCfg
);
taosSetServerCfg
(
tsCfg
);
}
...
...
@@ -436,6 +444,6 @@ void taosCfgDynamicOptions(const char *option, const char *value) {
if
(
strcasecmp
(
option
,
"resetlog"
)
==
0
)
{
taosResetLog
();
// taosPrintCfg(
);
cfgDumpCfg
(
tsCfg
,
1
,
false
);
}
}
\ No newline at end of file
source/dnode/mgmt/daemon/inc/dmnInt.h
浏览文件 @
5e3e0485
...
...
@@ -28,7 +28,6 @@
extern
"C"
{
#endif
SDnodeEnvCfg
dmnGetEnvCfg
();
SDnodeObjCfg
dmnGetObjCfg
();
void
dmnDumpCfg
();
...
...
source/dnode/mgmt/daemon/src/dmnCfg.c
浏览文件 @
5e3e0485
...
...
@@ -17,18 +17,6 @@
#include "dmnInt.h"
#include "tconfig.h"
SDnodeEnvCfg
dmnGetEnvCfg
()
{
SConfig
*
pCfg
=
taosGetCfg
();
SDnodeEnvCfg
envCfg
=
{
0
};
const
char
*
vstr
=
cfgGetItem
(
pCfg
,
"version"
)
->
str
;
envCfg
.
sver
=
30000000
;
envCfg
.
numOfCores
=
cfgGetItem
(
pCfg
,
"numOfCores"
)
->
i32
;
envCfg
.
numOfCommitThreads
=
(
uint16_t
)
cfgGetItem
(
pCfg
,
"numOfCommitThreads"
)
->
i32
;
envCfg
.
enableTelem
=
cfgGetItem
(
pCfg
,
"telemetryReporting"
)
->
bval
;
return
envCfg
;
}
SDnodeObjCfg
dmnGetObjCfg
()
{
SConfig
*
pCfg
=
taosGetCfg
();
SDnodeObjCfg
objCfg
=
{
0
};
...
...
source/dnode/mgmt/daemon/src/dmnMain.c
浏览文件 @
5e3e0485
...
...
@@ -73,14 +73,13 @@ static int32_t dmnParseOption(int32_t argc, char const *argv[]) {
}
int32_t
dmnRunDnode
()
{
SDnodeEnvCfg
envCfg
=
dmnGetEnvCfg
();
if
(
dndInit
(
&
envCfg
)
!=
0
)
{
if
(
dndInit
()
!=
0
)
{
uInfo
(
"Failed to start TDengine, please check the log"
);
return
-
1
;
}
SDnodeObjCfg
objCfg
=
dmnGetObjCfg
();
SDnode
*
pDnode
=
dndCreate
(
&
objCfg
);
SDnode
*
pDnode
=
dndCreate
(
&
objCfg
);
if
(
pDnode
==
NULL
)
{
uInfo
(
"Failed to start TDengine, please check the log"
);
return
-
1
;
...
...
@@ -93,6 +92,7 @@ int32_t dmnRunDnode() {
dndClose
(
pDnode
);
dndCleanup
();
taosCloseLog
();
taosCleanupCfg
();
return
0
;
}
...
...
@@ -113,12 +113,12 @@ int main(int argc, char const *argv[]) {
return
0
;
}
if
(
taosCreateLog
(
"taosdlog"
,
1
,
configDir
,
dmn
.
envFile
,
dmn
.
apolloUrl
,
1
)
!=
0
)
{
if
(
taosCreateLog
(
"taosdlog"
,
1
,
configDir
,
dmn
.
envFile
,
dmn
.
apolloUrl
,
0
)
!=
0
)
{
uInfo
(
"Failed to start TDengine since read config error"
);
return
-
1
;
}
if
(
taosInitCfg
(
configDir
,
dmn
.
envFile
,
dmn
.
apolloUrl
,
1
)
!=
0
)
{
if
(
taosInitCfg
(
configDir
,
dmn
.
envFile
,
dmn
.
apolloUrl
,
0
)
!=
0
)
{
uInfo
(
"Failed to start TDengine since read config error"
);
return
-
1
;
}
...
...
@@ -129,7 +129,5 @@ int main(int argc, char const *argv[]) {
return
0
;
}
int32_t
code
=
dmnRunDnode
();
taosCleanupCfg
();
return
code
;
return
dmnRunDnode
();
}
source/dnode/mgmt/impl/inc/dndEnv.h
浏览文件 @
5e3e0485
...
...
@@ -124,7 +124,6 @@ typedef struct {
typedef
struct
SDnode
{
EStat
stat
;
SDnodeObjCfg
cfg
;
SDnodeEnvCfg
env
;
SDnodeDir
dir
;
FileFd
lockFd
;
SDnodeMgmt
dmgmt
;
...
...
@@ -138,11 +137,6 @@ typedef struct SDnode {
SStartupReq
startup
;
}
SDnode
;
typedef
struct
{
int8_t
once
;
SDnodeEnvCfg
cfg
;
}
SDnodeEnv
;
#ifdef __cplusplus
}
#endif
...
...
source/dnode/mgmt/impl/src/dndBnode.c
浏览文件 @
5e3e0485
...
...
@@ -179,7 +179,7 @@ static void dndBuildBnodeOption(SDnode *pDnode, SBnodeOpt *pOption) {
pOption
->
sendRedirectRspFp
=
dndSendRedirectRsp
;
pOption
->
dnodeId
=
dndGetDnodeId
(
pDnode
);
pOption
->
clusterId
=
dndGetClusterId
(
pDnode
);
pOption
->
sver
=
pDnode
->
env
.
sver
;
pOption
->
sver
=
tsVersion
;
}
static
int32_t
dndOpenBnode
(
SDnode
*
pDnode
)
{
...
...
source/dnode/mgmt/impl/src/dndEnv.c
浏览文件 @
5e3e0485
...
...
@@ -25,7 +25,7 @@
#include "tfs.h"
#include "wal.h"
static
SDnodeEnv
dndEnv
=
{
0
}
;
static
int8_t
once
=
DND_ENV_INIT
;
EStat
dndGetStat
(
SDnode
*
pDnode
)
{
return
pDnode
->
stat
;
}
...
...
@@ -137,7 +137,6 @@ static int32_t dndCreateImp(SDnode *pDnode, SDnodeObjCfg *pCfg) {
}
memcpy
(
&
pDnode
->
cfg
,
pCfg
,
sizeof
(
SDnodeObjCfg
));
memcpy
(
&
pDnode
->
env
,
&
dndEnv
.
cfg
,
sizeof
(
SDnodeEnvCfg
));
return
0
;
}
...
...
@@ -259,8 +258,8 @@ void dndClose(SDnode *pDnode) {
dInfo
(
"dnode object is closed, data:%p"
,
pDnode
);
}
int32_t
dndInit
(
const
SDnodeEnvCfg
*
pCfg
)
{
if
(
atomic_val_compare_exchange_8
(
&
dndEnv
.
once
,
DND_ENV_INIT
,
DND_ENV_READY
)
!=
DND_ENV_INIT
)
{
int32_t
dndInit
()
{
if
(
atomic_val_compare_exchange_8
(
&
once
,
DND_ENV_INIT
,
DND_ENV_READY
)
!=
DND_ENV_INIT
)
{
terrno
=
TSDB_CODE_REPEAT_INIT
;
dError
(
"failed to init dnode env since %s"
,
terrstr
());
return
-
1
;
...
...
@@ -283,8 +282,8 @@ int32_t dndInit(const SDnodeEnvCfg *pCfg) {
}
SVnodeOpt
vnodeOpt
=
{
.
sver
=
pCfg
->
sver
,
.
nthreads
=
pCfg
->
n
umOfCommitThreads
,
.
sver
=
tsVersion
,
.
nthreads
=
tsN
umOfCommitThreads
,
.
putReqToVQueryQFp
=
dndPutReqToVQueryQ
,
.
sendReqToDnodeFp
=
dndSendReqToDnode
};
...
...
@@ -295,13 +294,12 @@ int32_t dndInit(const SDnodeEnvCfg *pCfg) {
return
-
1
;
}
memcpy
(
&
dndEnv
.
cfg
,
pCfg
,
sizeof
(
SDnodeEnvCfg
));
dInfo
(
"dnode env is initialized"
);
return
0
;
}
void
dndCleanup
()
{
if
(
atomic_val_compare_exchange_8
(
&
dndEnv
.
once
,
DND_ENV_READY
,
DND_ENV_CLEANUP
)
!=
DND_ENV_READY
)
{
if
(
atomic_val_compare_exchange_8
(
&
once
,
DND_ENV_READY
,
DND_ENV_CLEANUP
)
!=
DND_ENV_READY
)
{
dError
(
"dnode env is already cleaned up"
);
return
;
}
...
...
source/dnode/mgmt/impl/src/dndMgmt.c
浏览文件 @
5e3e0485
...
...
@@ -357,13 +357,13 @@ void dndSendStatusReq(SDnode *pDnode) {
SDnodeMgmt
*
pMgmt
=
&
pDnode
->
dmgmt
;
taosRLockLatch
(
&
pMgmt
->
latch
);
req
.
sver
=
pDnode
->
env
.
sver
;
req
.
sver
=
tsVersion
;
req
.
dver
=
pMgmt
->
dver
;
req
.
dnodeId
=
pMgmt
->
dnodeId
;
req
.
clusterId
=
pMgmt
->
clusterId
;
req
.
rebootTime
=
pMgmt
->
rebootTime
;
req
.
updateTime
=
pMgmt
->
updateTime
;
req
.
numOfCores
=
pDnode
->
env
.
n
umOfCores
;
req
.
numOfCores
=
tsN
umOfCores
;
req
.
numOfSupportVnodes
=
pDnode
->
cfg
.
numOfSupportVnodes
;
memcpy
(
req
.
dnodeEp
,
pDnode
->
cfg
.
localEp
,
TSDB_EP_LEN
);
...
...
source/dnode/mgmt/impl/src/dndMnode.c
浏览文件 @
5e3e0485
...
...
@@ -273,8 +273,8 @@ static void dndInitMnodeOption(SDnode *pDnode, SMnodeOpt *pOption) {
pOption
->
putReqToMReadQFp
=
dndPutMsgToMReadQ
;
pOption
->
dnodeId
=
dndGetDnodeId
(
pDnode
);
pOption
->
clusterId
=
dndGetClusterId
(
pDnode
);
pOption
->
cfg
.
sver
=
pDnode
->
env
.
sver
;
pOption
->
cfg
.
enableTelem
=
pDnode
->
env
.
enableTelem
;
pOption
->
cfg
.
sver
=
tsVersion
;
pOption
->
cfg
.
enableTelem
=
tsEnableTelemetryReporting
;
}
static
void
dndBuildMnodeDeployOption
(
SDnode
*
pDnode
,
SMnodeOpt
*
pOption
)
{
...
...
source/dnode/mgmt/impl/src/dndQnode.c
浏览文件 @
5e3e0485
...
...
@@ -185,7 +185,7 @@ static void dndBuildQnodeOption(SDnode *pDnode, SQnodeOpt *pOption) {
pOption
->
sendRedirectRspFp
=
dndSendRedirectRsp
;
pOption
->
dnodeId
=
dndGetDnodeId
(
pDnode
);
pOption
->
clusterId
=
dndGetClusterId
(
pDnode
);
pOption
->
sver
=
pDnode
->
env
.
sver
;
pOption
->
sver
=
tsVersion
;
}
static
int32_t
dndOpenQnode
(
SDnode
*
pDnode
)
{
...
...
source/dnode/mgmt/impl/src/dndSnode.c
浏览文件 @
5e3e0485
...
...
@@ -179,7 +179,7 @@ static void dndBuildSnodeOption(SDnode *pDnode, SSnodeOpt *pOption) {
pOption
->
sendRedirectRspFp
=
dndSendRedirectRsp
;
pOption
->
dnodeId
=
dndGetDnodeId
(
pDnode
);
pOption
->
clusterId
=
dndGetClusterId
(
pDnode
);
pOption
->
sver
=
pDnode
->
env
.
sver
;
pOption
->
sver
=
tsVersion
;
}
static
int32_t
dndOpenSnode
(
SDnode
*
pDnode
)
{
...
...
source/dnode/mgmt/impl/src/dndTransport.c
浏览文件 @
5e3e0485
...
...
@@ -344,7 +344,7 @@ static int32_t dndInitServer(SDnode *pDnode) {
STransMgmt
*
pMgmt
=
&
pDnode
->
tmgmt
;
dndInitMsgFp
(
pMgmt
);
int32_t
numOfThreads
=
(
int32_t
)((
pDnode
->
env
.
n
umOfCores
*
tsNumOfThreadsPerCore
)
/
2
.
0
);
int32_t
numOfThreads
=
(
int32_t
)((
tsN
umOfCores
*
tsNumOfThreadsPerCore
)
/
2
.
0
);
if
(
numOfThreads
<
1
)
{
numOfThreads
=
1
;
}
...
...
source/dnode/mgmt/impl/src/dndVnodes.c
浏览文件 @
5e3e0485
...
...
@@ -421,7 +421,7 @@ static int32_t dndOpenVnodes(SDnode *pDnode) {
pMgmt
->
totalVnodes
=
numOfVnodes
;
int32_t
threadNum
=
pDnode
->
env
.
n
umOfCores
;
int32_t
threadNum
=
tsN
umOfCores
;
#if 1
threadNum
=
1
;
#endif
...
...
@@ -874,11 +874,11 @@ static int32_t dndInitVnodeWorkers(SDnode *pDnode) {
SVnodesMgmt
*
pMgmt
=
&
pDnode
->
vmgmt
;
int32_t
maxFetchThreads
=
4
;
int32_t
minFetchThreads
=
TMIN
(
maxFetchThreads
,
pDnode
->
env
.
n
umOfCores
);
int32_t
minQueryThreads
=
TMAX
((
int32_t
)(
pDnode
->
env
.
n
umOfCores
*
tsRatioOfQueryCores
),
1
);
int32_t
minFetchThreads
=
TMIN
(
maxFetchThreads
,
tsN
umOfCores
);
int32_t
minQueryThreads
=
TMAX
((
int32_t
)(
tsN
umOfCores
*
tsRatioOfQueryCores
),
1
);
int32_t
maxQueryThreads
=
minQueryThreads
;
int32_t
maxWriteThreads
=
TMAX
(
pDnode
->
env
.
n
umOfCores
,
1
);
int32_t
maxSyncThreads
=
TMAX
(
pDnode
->
env
.
n
umOfCores
/
2
,
1
);
int32_t
maxWriteThreads
=
TMAX
(
tsN
umOfCores
,
1
);
int32_t
maxSyncThreads
=
TMAX
(
tsN
umOfCores
/
2
,
1
);
SQWorkerPool
*
pQPool
=
&
pMgmt
->
queryPool
;
pQPool
->
name
=
"vnode-query"
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录