Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
d9072005
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1187
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看板
未验证
提交
d9072005
编写于
3月 03, 2022
作者:
S
Shengliang Guan
提交者:
GitHub
3月 03, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #10531 from taosdata/feature/config
monitor
上级
405e9e2c
2bf46ddc
变更
15
展开全部
隐藏空白更改
内联
并排
Showing
15 changed file
with
298 addition
and
257 deletion
+298
-257
include/libs/monitor/monitor.h
include/libs/monitor/monitor.h
+9
-9
include/libs/tfs/tfs.h
include/libs/tfs/tfs.h
+9
-0
include/os/osEnv.h
include/os/osEnv.h
+3
-3
include/os/osSysinfo.h
include/os/osSysinfo.h
+12
-12
source/common/src/tglobal.c
source/common/src/tglobal.c
+3
-7
source/dnode/mgmt/impl/inc/dndEnv.h
source/dnode/mgmt/impl/inc/dndEnv.h
+2
-3
source/dnode/mgmt/impl/inc/dndMnode.h
source/dnode/mgmt/impl/inc/dndMnode.h
+1
-0
source/dnode/mgmt/impl/src/dndEnv.c
source/dnode/mgmt/impl/src/dndEnv.c
+8
-1
source/dnode/mgmt/impl/src/dndMgmt.c
source/dnode/mgmt/impl/src/dndMgmt.c
+38
-10
source/dnode/mgmt/impl/src/dndMnode.c
source/dnode/mgmt/impl/src/dndMnode.c
+7
-0
source/dnode/mnode/impl/src/mndTelem.c
source/dnode/mnode/impl/src/mndTelem.c
+6
-9
source/libs/tfs/CMakeLists.txt
source/libs/tfs/CMakeLists.txt
+1
-1
source/libs/tfs/src/tfs.c
source/libs/tfs/src/tfs.c
+21
-0
source/os/src/osEnv.c
source/os/src/osEnv.c
+8
-3
source/os/src/osSysinfo.c
source/os/src/osSysinfo.c
+170
-199
未找到文件。
include/libs/monitor/monitor.h
浏览文件 @
d9072005
...
...
@@ -88,18 +88,18 @@ typedef struct {
float
cpu_engine
;
float
cpu_system
;
float
cpu_cores
;
float
mem_engine
;
// M
B
float
mem_system
;
// M
B
float
mem_total
;
// M
B
int64_t
mem_engine
;
// K
B
int64_t
mem_system
;
// K
B
int64_t
mem_total
;
// K
B
float
disk_engine
;
// GB
float
disk_used
;
// GB
float
disk_total
;
// GB
float
net_in
;
// Kb/s
float
net_out
;
// Kb/s
float
io_read
;
// Mb/s
float
io_write
;
// Mb/s
float
io_read_disk
;
// Mb/s
float
io_write_disk
;
// Mb/s
int64_t
net_in
;
int64_t
net_out
;
float
io_read
;
float
io_write
;
float
io_read_disk
;
float
io_write_disk
;
int32_t
req_select
;
float
req_select_rate
;
int32_t
req_insert
;
...
...
include/libs/tfs/tfs.h
浏览文件 @
d9072005
...
...
@@ -17,6 +17,7 @@
#define _TD_TFS_H_
#include "tdef.h"
#include "monitor.h"
#ifdef __cplusplus
extern
"C"
{
...
...
@@ -237,6 +238,14 @@ const STfsFile *tfsReaddir(STfsDir *pDir);
*/
void
tfsClosedir
(
STfsDir
*
pDir
);
/**
* @brief Get disk info of tfs.
*
* @param pTfs The fs object.
* @param pInfo The info object.
*/
int32_t
tfsGetMonitorInfo
(
STfs
*
pTfs
,
SMonDiskInfo
*
pInfo
);
#ifdef __cplusplus
}
#endif
...
...
include/os/osEnv.h
浏览文件 @
d9072005
...
...
@@ -28,11 +28,11 @@ extern char tsCharset[];
extern
char
tsLocale
[];
extern
int8_t
tsDaylight
;
extern
bool
tsEnableCoreFile
;
extern
int64_t
tsPageSize
;
extern
int64_t
tsPageSize
KB
;
extern
int64_t
tsOpenMax
;
extern
int64_t
tsStreamMax
;
extern
int32_t
tsNumOfCores
;
extern
int
32_t
tsTotalMemoryM
B
;
extern
float
tsNumOfCores
;
extern
int
64_t
tsTotalMemoryK
B
;
extern
char
configDir
[];
extern
char
tsDataDir
[];
...
...
include/os/osSysinfo.h
浏览文件 @
d9072005
...
...
@@ -34,19 +34,19 @@ typedef struct {
}
SDiskSpace
;
void
taosGetSystemInfo
();
bool
taosGetEmail
(
char
*
email
,
int32_t
maxLen
);
bool
taosGetOsReleaseName
(
char
*
releaseName
,
int32_t
maxLen
);
bool
taosGetCpuInfo
(
char
*
cpuModel
,
int32_t
maxLen
,
int32_
t
*
numOfCores
);
int32_t
taosGetCpuCores
();
bool
taosGetCpuUsage
(
float
*
sysCpuUsage
,
float
*
procCpuUsag
e
);
bool
taosGetTotalSysMemoryKB
(
uint64_t
*
kb
);
bool
taosGetProcMemory
(
float
*
memoryUsedMB
);
//
bool
taosGetSysMemory
(
float
*
memoryUsedMB
);
//
int32_t
taosGetEmail
(
char
*
email
,
int32_t
maxLen
);
int32_t
taosGetOsReleaseName
(
char
*
releaseName
,
int32_t
maxLen
);
int32_t
taosGetCpuInfo
(
char
*
cpuModel
,
int32_t
maxLen
,
floa
t
*
numOfCores
);
int32_t
taosGetCpuCores
(
float
*
numOfCores
);
int32_t
taosGetCpuUsage
(
float
*
cpu_system
,
float
*
cpu_engin
e
);
int32_t
taosGetTotalMemory
(
int64_t
*
totalKB
);
int32_t
taosGetProcMemory
(
int64_t
*
usedKB
);
int32_t
taosGetSysMemory
(
int64_t
*
usedKB
);
int32_t
taosGetDiskSize
(
char
*
dataDir
,
SDiskSize
*
diskSize
);
bool
taosReadProcIO
(
int64_t
*
rchars
,
int64_t
*
wchars
);
bool
taosGetProcIO
(
float
*
readKB
,
float
*
writeKB
);
bool
taosGetCardInfo
(
int64_t
*
bytes
,
int64_t
*
rbytes
,
int64_t
*
tbytes
);
bool
taosGetBandSpeed
(
float
*
bandSpeedKb
);
int32_t
taosReadProcIO
(
int64_t
*
rchars
,
int64_t
*
wchars
);
int32_t
taosGetProcIO
(
float
*
readKB
,
float
*
writeKB
);
int32_t
taosGetCardInfo
(
int64_t
*
bytes
,
int64_t
*
rbytes
,
int64_t
*
tbytes
);
int32_t
taosGetBandSpeed
(
float
*
bandSpeedKb
);
int32_t
taosSystem
(
const
char
*
cmd
);
void
taosKillSystem
();
...
...
source/common/src/tglobal.c
浏览文件 @
d9072005
...
...
@@ -279,11 +279,11 @@ static int32_t taosAddSystemCfg(SConfig *pCfg) {
if
(
cfgAddLocale
(
pCfg
,
"locale"
,
tsLocale
)
!=
0
)
return
-
1
;
if
(
cfgAddCharset
(
pCfg
,
"charset"
,
tsCharset
)
!=
0
)
return
-
1
;
if
(
cfgAddBool
(
pCfg
,
"enableCoreFile"
,
1
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt32
(
pCfg
,
"numOfCores"
,
tsNumOfCores
,
1
,
100000
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt32
(
pCfg
,
"pageSize(KB)"
,
tsPageSize
,
0
,
INT64_MAX
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddFloat
(
pCfg
,
"numOfCores"
,
tsNumOfCores
,
0
,
100000
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt64
(
pCfg
,
"openMax"
,
tsOpenMax
,
0
,
INT64_MAX
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt64
(
pCfg
,
"streamMax"
,
tsStreamMax
,
0
,
INT64_MAX
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt32
(
pCfg
,
"totalMemory(MB)"
,
tsTotalMemoryMB
,
0
,
INT32_MAX
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt32
(
pCfg
,
"pageSize(KB)"
,
tsPageSizeKB
,
0
,
INT64_MAX
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddInt64
(
pCfg
,
"totalMemory(KB)"
,
tsTotalMemoryKB
,
0
,
INT64_MAX
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddString
(
pCfg
,
"os sysname"
,
info
.
sysname
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddString
(
pCfg
,
"os nodename"
,
info
.
nodename
,
1
)
!=
0
)
return
-
1
;
if
(
cfgAddString
(
pCfg
,
"os release"
,
info
.
release
,
1
)
!=
0
)
return
-
1
;
...
...
@@ -404,10 +404,6 @@ static void taosSetSystemCfg(SConfig *pCfg) {
const
char
*
charset
=
cfgGetItem
(
pCfg
,
"charset"
)
->
str
;
taosSetSystemLocale
(
locale
,
charset
);
if
(
tsNumOfCores
<=
1
)
{
tsNumOfCores
=
2
;
}
bool
enableCore
=
cfgGetItem
(
pCfg
,
"enableCoreFile"
)
->
bval
;
taosSetConsoleEcho
(
enableCore
);
...
...
source/dnode/mgmt/impl/inc/dndEnv.h
浏览文件 @
d9072005
...
...
@@ -31,7 +31,7 @@ typedef struct {
SDnode
*
pDnode
;
STaosQueue
*
queue
;
union
{
SQWorkerPool
pool
;
SQWorkerPool
pool
;
SWWorkerPool
mpool
;
};
}
SDnodeWorker
;
...
...
@@ -137,8 +137,7 @@ typedef struct SDnode {
SStartupReq
startup
;
}
SDnode
;
int32_t
dndGetDiskInfo
(
SDnode
*
pDnode
,
SMonDiskInfo
*
pInfo
);
int32_t
dndGetMonitorDiskInfo
(
SDnode
*
pDnode
,
SMonDiskInfo
*
pInfo
);
#ifdef __cplusplus
}
...
...
source/dnode/mgmt/impl/inc/dndMnode.h
浏览文件 @
d9072005
...
...
@@ -34,6 +34,7 @@ int32_t dndProcessDropMnodeReq(SDnode *pDnode, SRpcMsg *pRpcMsg);
int32_t
dndGetMnodeMonitorInfo
(
SDnode
*
pDnode
,
SMonClusterInfo
*
pClusterInfo
,
SMonVgroupInfo
*
pVgroupInfo
,
SMonGrantInfo
*
pGrantInfo
);
int8_t
dndIsMnode
(
SDnode
*
pDnode
);
#ifdef __cplusplus
}
...
...
source/dnode/mgmt/impl/src/dndEnv.c
浏览文件 @
d9072005
...
...
@@ -324,4 +324,11 @@ void dndCleanup() {
dInfo
(
"dnode env is cleaned up"
);
}
int32_t
dndGetDiskInfo
(
SDnode
*
pDnode
,
SMonDiskInfo
*
pInfo
)
{
return
0
;
}
\ No newline at end of file
int32_t
dndGetMonitorDiskInfo
(
SDnode
*
pDnode
,
SMonDiskInfo
*
pInfo
)
{
tstrncpy
(
pInfo
->
logdir
.
name
,
tsLogDir
,
sizeof
(
pInfo
->
logdir
.
name
));
pInfo
->
logdir
.
size
=
tsLogSpace
.
size
;
tstrncpy
(
pInfo
->
tempdir
.
name
,
tsTempDir
,
sizeof
(
pInfo
->
tempdir
.
name
));
pInfo
->
tempdir
.
size
=
tsTempSpace
.
size
;
return
tfsGetMonitorInfo
(
pDnode
->
pTfs
,
pInfo
);
}
\ No newline at end of file
source/dnode/mgmt/impl/src/dndMgmt.c
浏览文件 @
d9072005
...
...
@@ -474,13 +474,38 @@ void dndProcessStartupReq(SDnode *pDnode, SRpcMsg *pReq) {
rpcSendResponse
(
&
rpcRsp
);
}
static
int32_t
dndGet
BasicInfo
(
SDnode
*
pDnode
,
SMonBasicInfo
*
pInfo
)
{
static
void
dndGetMonitor
BasicInfo
(
SDnode
*
pDnode
,
SMonBasicInfo
*
pInfo
)
{
pInfo
->
dnode_id
=
dndGetDnodeId
(
pDnode
);
tstrncpy
(
pInfo
->
dnode_ep
,
tsLocalEp
,
TSDB_EP_LEN
);
return
0
;
}
static
int32_t
dndGetDnodeInfo
(
SDnode
*
pDnode
,
SMonDnodeInfo
*
pInfo
)
{
return
0
;
}
static
void
dndGetMonitorDnodeInfo
(
SDnode
*
pDnode
,
SMonDnodeInfo
*
pInfo
)
{
pInfo
->
uptime
=
(
taosGetTimestampMs
()
-
pDnode
->
dmgmt
.
rebootTime
)
/
(
86400000
.
0
f
);
taosGetCpuUsage
(
&
pInfo
->
cpu_engine
,
&
pInfo
->
cpu_system
);
pInfo
->
cpu_cores
=
tsNumOfCores
;
taosGetProcMemory
(
&
pInfo
->
mem_engine
);
taosGetSysMemory
(
&
pInfo
->
mem_system
);
pInfo
->
mem_total
=
tsTotalMemoryKB
;
pInfo
->
disk_engine
=
0
;
pInfo
->
disk_used
=
tsDataSpace
.
size
.
used
/
(
1024
*
1024
*
1024
.
0
);
pInfo
->
disk_total
=
tsDataSpace
.
size
.
avail
/
(
1024
*
1024
*
1024
.
0
);
taosGetCardInfo
(
NULL
,
&
pInfo
->
net_in
,
&
pInfo
->
net_out
);
taosGetProcIO
(
&
pInfo
->
io_read
,
&
pInfo
->
io_write
);
pInfo
->
io_read_disk
=
0
;
pInfo
->
io_write_disk
=
0
;
pInfo
->
req_select
=
0
;
pInfo
->
req_select_rate
=
0
;
pInfo
->
req_insert
=
0
;
pInfo
->
req_insert_success
=
0
;
pInfo
->
req_insert_rate
=
0
;
pInfo
->
req_insert_batch
=
0
;
pInfo
->
req_insert_batch_success
=
0
;
pInfo
->
req_insert_batch_rate
=
0
;
pInfo
->
errors
=
0
;
pInfo
->
vnodes_num
=
0
;
pInfo
->
masters
=
0
;
pInfo
->
has_mnode
=
dndIsMnode
(
pDnode
);
}
static
void
dndSendMonitorReport
(
SDnode
*
pDnode
)
{
if
(
!
tsEnableMonitor
||
tsMonitorFqdn
[
0
]
==
0
||
tsMonitorPort
==
0
)
return
;
...
...
@@ -490,9 +515,8 @@ static void dndSendMonitorReport(SDnode *pDnode) {
if
(
pMonitor
==
NULL
)
return
;
SMonBasicInfo
basicInfo
=
{
0
};
if
(
dndGetBasicInfo
(
pDnode
,
&
basicInfo
)
==
0
)
{
monSetBasicInfo
(
pMonitor
,
&
basicInfo
);
}
dndGetMonitorBasicInfo
(
pDnode
,
&
basicInfo
);
monSetBasicInfo
(
pMonitor
,
&
basicInfo
);
SMonClusterInfo
clusterInfo
=
{
0
};
SMonVgroupInfo
vgroupInfo
=
{
0
};
...
...
@@ -504,15 +528,19 @@ static void dndSendMonitorReport(SDnode *pDnode) {
}
SMonDnodeInfo
dnodeInfo
=
{
0
};
if
(
dndGetDnodeInfo
(
pDnode
,
&
dnodeInfo
)
==
0
)
{
monSetDnodeInfo
(
pMonitor
,
&
dnodeInfo
);
}
dndGetMonitorDnodeInfo
(
pDnode
,
&
dnodeInfo
);
monSetDnodeInfo
(
pMonitor
,
&
dnodeInfo
);
SMonDiskInfo
diskInfo
=
{
0
};
if
(
dndGetDiskInfo
(
pDnode
,
&
diskInfo
)
==
0
)
{
if
(
dndGet
Monitor
DiskInfo
(
pDnode
,
&
diskInfo
)
==
0
)
{
monSetDiskInfo
(
pMonitor
,
&
diskInfo
);
}
taosArrayDestroy
(
clusterInfo
.
dnodes
);
taosArrayDestroy
(
clusterInfo
.
mnodes
);
taosArrayDestroy
(
vgroupInfo
.
vgroups
);
taosArrayDestroy
(
diskInfo
.
datadirs
);
monSendReport
(
pMonitor
);
monCleanupMonitorInfo
(
pMonitor
);
}
...
...
source/dnode/mgmt/impl/src/dndMnode.c
浏览文件 @
d9072005
...
...
@@ -639,4 +639,11 @@ int32_t dndGetMnodeMonitorInfo(SDnode *pDnode, SMonClusterInfo *pClusterInfo, SM
int32_t
code
=
mndGetMonitorInfo
(
pMnode
,
pClusterInfo
,
pVgroupInfo
,
pGrantInfo
);
dndReleaseMnode
(
pDnode
,
pMnode
);
return
code
;
}
int8_t
dndIsMnode
(
SDnode
*
pDnode
)
{
SMnode
*
pMnode
=
dndAcquireMnode
(
pDnode
);
if
(
pMnode
==
NULL
)
return
0
;
dndReleaseMnode
(
pDnode
,
pMnode
);
return
1
;
}
\ No newline at end of file
source/dnode/mnode/impl/src/mndTelem.c
浏览文件 @
d9072005
...
...
@@ -52,23 +52,20 @@ static char* mndBuildTelemetryReport(SMnode* pMnode) {
tjsonAddStringToObject
(
pJson
,
"instanceId"
,
clusterName
);
tjsonAddDoubleToObject
(
pJson
,
"reportVersion"
,
1
);
if
(
taosGetOsReleaseName
(
tmp
,
sizeof
(
tmp
)))
{
if
(
taosGetOsReleaseName
(
tmp
,
sizeof
(
tmp
))
==
0
)
{
tjsonAddStringToObject
(
pJson
,
"os"
,
tmp
);
}
int32_
t
numOfCores
=
0
;
if
(
taosGetCpuInfo
(
tmp
,
sizeof
(
tmp
),
&
numOfCores
))
{
floa
t
numOfCores
=
0
;
if
(
taosGetCpuInfo
(
tmp
,
sizeof
(
tmp
),
&
numOfCores
)
==
0
)
{
tjsonAddStringToObject
(
pJson
,
"cpuModel"
,
tmp
);
tjsonAddDoubleToObject
(
pJson
,
"numOfCpu"
,
numOfCores
);
}
else
{
tjsonAddDoubleToObject
(
pJson
,
"numOfCpu"
,
t
aosGetCpuCores
()
);
tjsonAddDoubleToObject
(
pJson
,
"numOfCpu"
,
t
sNumOfCores
);
}
uint64_t
memoryKB
=
0
;
if
(
taosGetTotalSysMemoryKB
(
&
memoryKB
))
{
snprintf
(
tmp
,
sizeof
(
tmp
),
"%"
PRIu64
" kB"
,
memoryKB
);
tjsonAddStringToObject
(
pJson
,
"memory"
,
tmp
);
}
snprintf
(
tmp
,
sizeof
(
tmp
),
"%"
PRId64
" kB"
,
tsTotalMemoryKB
);
tjsonAddStringToObject
(
pJson
,
"memory"
,
tmp
);
tjsonAddStringToObject
(
pJson
,
"version"
,
version
);
tjsonAddStringToObject
(
pJson
,
"buildInfo"
,
buildinfo
);
...
...
source/libs/tfs/CMakeLists.txt
浏览文件 @
d9072005
...
...
@@ -6,7 +6,7 @@ target_include_directories(
PRIVATE
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/inc"
)
target_link_libraries
(
tfs os util common
)
target_link_libraries
(
tfs os util common
monitor
)
if
(
${
BUILD_TEST
}
)
add_subdirectory
(
test
)
...
...
source/libs/tfs/src/tfs.c
浏览文件 @
d9072005
...
...
@@ -544,3 +544,24 @@ static STfsDisk *tfsNextDisk(STfs *pTfs, SDiskIter *pIter) {
return
pDisk
;
}
int32_t
tfsGetMonitorInfo
(
STfs
*
pTfs
,
SMonDiskInfo
*
pInfo
)
{
pInfo
->
datadirs
=
taosArrayInit
(
32
,
sizeof
(
SMonDiskDesc
));
if
(
pInfo
->
datadirs
==
NULL
)
return
-
1
;
tfsUpdateSize
(
pTfs
);
tfsLock
(
pTfs
);
for
(
int32_t
level
=
0
;
level
<
pTfs
->
nlevel
;
level
++
)
{
STfsTier
*
pTier
=
&
pTfs
->
tiers
[
level
];
for
(
int32_t
disk
=
0
;
disk
<
pTier
->
ndisk
;
++
disk
)
{
STfsDisk
*
pDisk
=
pTier
->
disks
[
disk
];
SMonDiskDesc
dinfo
=
{
0
};
dinfo
.
size
=
pDisk
->
size
;
dinfo
.
level
=
pDisk
->
level
;
tstrncpy
(
dinfo
.
name
,
pDisk
->
path
,
sizeof
(
dinfo
.
name
));
taosArrayPush
(
pInfo
->
datadirs
,
&
dinfo
);
}
}
tfsUnLock
(
pTfs
);
}
\ No newline at end of file
source/os/src/osEnv.c
浏览文件 @
d9072005
...
...
@@ -31,11 +31,11 @@ char tsLocale[TD_LOCALE_LEN] = {0};
char
tsCharset
[
TD_CHARSET_LEN
]
=
{
0
};
int8_t
tsDaylight
=
0
;
bool
tsEnableCoreFile
=
0
;
int64_t
tsPageSize
=
0
;
int64_t
tsPageSize
KB
=
0
;
int64_t
tsOpenMax
=
0
;
int64_t
tsStreamMax
=
0
;
int32_t
tsNumOfCores
=
0
;
int
32_t
tsTotalMemoryM
B
=
0
;
float
tsNumOfCores
=
0
;
int
64_t
tsTotalMemoryK
B
=
0
;
void
osInit
()
{
srand
(
taosSafeRand
());
...
...
@@ -44,6 +44,11 @@ void osInit() {
taosSetSystemTimezone
(
tsTimezone
,
tsTimezone
,
&
tsDaylight
);
taosGetSystemInfo
();
// deadlock in query
if
(
tsNumOfCores
<
2
)
{
tsNumOfCores
=
2
;
}
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
taosWinSocketInit
();
...
...
source/os/src/osSysinfo.c
浏览文件 @
d9072005
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录