mirror of
https://gitee.com/openharmony/developtools_profiler
synced 2024-11-22 22:40:48 +00:00
update OpenHarmony 2.0 Canary
This commit is contained in:
parent
ec05f5afdf
commit
153bf94ba7
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.trp filter=lfs diff=lfs merge=lfs -text
|
||||
*.apk filter=lfs diff=lfs merge=lfs -text
|
||||
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.asm filter=lfs diff=lfs merge=lfs -text
|
||||
*.8svn filter=lfs diff=lfs merge=lfs -text
|
||||
*.9svn filter=lfs diff=lfs merge=lfs -text
|
||||
*.dylib filter=lfs diff=lfs merge=lfs -text
|
||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
||||
*.a filter=lfs diff=lfs merge=lfs -text
|
||||
*.so filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
178
LICENSE
Normal file
178
LICENSE
Normal file
@ -0,0 +1,178 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
73
OAT.xml
Executable file
73
OAT.xml
Executable file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Notes:
|
||||
This is project config file for OpenHarmony OSS Audit Tool, if you have any questions or concerns, please email chenyaxun@huawei.com.
|
||||
-->
|
||||
<!-- OAT(OSS Audit Tool) configuration guide:
|
||||
basedir: Root dir, the basedir + project path is the real source file location.
|
||||
licensefile:
|
||||
1.If the project don't have "LICENSE" in root dir, please define all the license files in this project in , OAT will check license files according to this rule.
|
||||
|
||||
tasklist(only for batch mode):
|
||||
1. task: Define oat check thread, each task will start a new thread.
|
||||
2. task name: Only an name, no practical effect.
|
||||
3. task policy: Default policy for projects under this task, this field is required and the specified policy must defined in policylist.
|
||||
4. task filter: Default filefilter for projects under this task, this field is required and the specified filefilter must defined in filefilterlist.
|
||||
5. task project: Projects to be checked, the path field define the source root dir of the project.
|
||||
|
||||
|
||||
policyList:
|
||||
1. policy: All policyitems will be merged to default OAT.xml rules, the name of policy doesn't affect OAT check process.
|
||||
2. policyitem: The fields type, name, path, desc is required, and the fields rule, group, filefilter is optional,the default value is:
|
||||
<policyitem type="" name="" path="" desc="" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
|
||||
3. policyitem type:
|
||||
"compatibility" is used to check license compatibility in the specified path;
|
||||
"license" is used to check source license header in the specified path;
|
||||
"copyright" is used to check source copyright header in the specified path;
|
||||
"import" is used to check source dependency in the specified path, such as import ... ,include ...
|
||||
"filetype" is used to check file type in the specified path, supported file types: archive, binary
|
||||
"filename" is used to check whether the specified file exists in the specified path(support projectroot in default OAT.xml), supported file names: LICENSE, README, README.OpenSource
|
||||
|
||||
4. policyitem name: This field is used for define the license, copyright, "*" means match all, the "!" prefix means could not match this value. For example, "!GPL" means can not use GPL license.
|
||||
5. policyitem path: This field is used for define the source file scope to apply this policyitem, the "!" prefix means exclude the files. For example, "!.*/lib/.*" means files in lib dir will be exclude while process this policyitem.
|
||||
6. policyitem rule and group: These two fields are used together to merge policy results. "may" policyitems in the same group means any one in this group passed, the result will be passed.
|
||||
7. policyitem filefilter: Used to bind filefilter which define filter rules.
|
||||
8. filefilter: Filter rules, the type filename is used to filter file name, the type filepath is used to filter file path.
|
||||
|
||||
Note:If the text contains special characters, please escape them according to the following rules:
|
||||
" == >
|
||||
& == >
|
||||
' == >
|
||||
< == >
|
||||
> == >
|
||||
-->
|
||||
<configuration>
|
||||
<oatconfig>
|
||||
<filefilterlist>
|
||||
<filefilter name="defaultPolicyFilter" desc="Filters for compatibility,license header policies">
|
||||
<filteritem type="filepath" name="device/plugins/memory_plugin/test/utresources/proc/.*" desc="test resource file, no license header"/>
|
||||
</filefilter>
|
||||
<filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies" >
|
||||
<filteritem type="filepath" name="device/plugins/memory_plugin/test/utresources/proc/.*" desc="test resource file, no copyright header"/>
|
||||
</filefilter>
|
||||
<filefilter name="binaryFileTypePolicyFilter" desc="Filters for binary file policies" >
|
||||
<filteritem type="filepath" name="host/ohosprofiler/src/main/resources/trace.db" desc="the binary file for host, the file is self-developed"/>
|
||||
<filteritem type="filepath" name="host/ohosprofiler/src/main/resources/ohos/devtools.tar" desc="the binary file for host, the file is self-developed"/>
|
||||
<filteritem type="filepath" name="host/ohosprofiler/src/test/resources/Demo.trace" desc="the binary file for host, the file is self-developed"/>
|
||||
</filefilter>
|
||||
</filefilterlist>
|
||||
</oatconfig>
|
||||
</configuration>
|
36
README.en.md
36
README.en.md
@ -1,36 +0,0 @@
|
||||
# developtools_profiler
|
||||
|
||||
#### Description
|
||||
Performance profiler that provides an analytics tool for the memory, bytrace plug-in, and IDE, as well as plug-in capabilities | 性能调优模块,提供了实时内存、bytrace插件和ide侧的分析工具,并提供了插件化能力
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
37
README.md
37
README.md
@ -1,37 +0,0 @@
|
||||
# developtools_profiler
|
||||
|
||||
#### 介绍
|
||||
Performance profiler that provides an analytics tool for the memory, bytrace plug-in, and IDE, as well as plug-in capabilities | 性能调优模块,提供了实时内存、bytrace插件和ide侧的分析工具,并提供了插件化能力
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
374
README_zh.md
Executable file
374
README_zh.md
Executable file
@ -0,0 +1,374 @@
|
||||
# 性能调优组件<a name="ZH-CN_TOPIC_0000001149491319"></a>
|
||||
|
||||
- [简介](#section6874544183112)
|
||||
- [架构图](#section1514713331342)
|
||||
- [目录](#section1742612449345)
|
||||
- [说明](#section2165102016359)
|
||||
- [接口说明](#section558917318367)
|
||||
- [使用说明](#section681316903611)
|
||||
- [调测验证:](#section35362541215)
|
||||
- [\#ZH-CN\_TOPIC\_0000001149491319/section3753165410213](#section3753165410213)
|
||||
|
||||
- [相关仓](#section1293495681320)
|
||||
|
||||
## 简介<a name="section6874544183112"></a>
|
||||
|
||||
性能调优组件包含系统和应用调优框架,旨在为开发者提供一套性能调优平台,可以用来分析内存、性能等问题。
|
||||
|
||||
该组件整体分为PC端和设备端两部分,PC端最终作为deveco studio的插件进行发布,内部主要包括分为UI绘制、设备管理、进程管理、插件管理、数据导入、数据存储、 数据分析、Session管理、配置管理等模块;设备端主要包括命令行工具、服务进程、插件集合、应用程序组件等模块。设备端提供了插件扩展能力,对外提供了插件接口,基于该扩展能力可以按需定义自己的能力,并集成到框架中来,目前基于插件能力已经完成了实时内存插件和trace插件。下文会重点对设备端提供的插件能力进行介绍。
|
||||
|
||||
## 架构图<a name="section1514713331342"></a>
|
||||
|
||||
![](figures/zh-cn_image_0000001162598155.png)
|
||||
|
||||
## 目录<a name="section1742612449345"></a>
|
||||
|
||||
```
|
||||
/developtools/profiler
|
||||
├── device # 设备侧代码目录
|
||||
│ └── base
|
||||
│ ├── include # 基础功能的头文件代码目录
|
||||
│ ├── src # 基础功能的源文件代码目录
|
||||
│ ├── test # 基础功能的测试代码目录
|
||||
│ └── cmds
|
||||
│ ├── include # 对外命令行模块的头文件代码目录
|
||||
│ ├── src # 对外命令行模块的源文件代码目录
|
||||
│ ├── test # 对外命令行模块的测试代码目录
|
||||
│ └── plugins
|
||||
│ ├── api # 插件模块对外提供的接口文件代码目录
|
||||
│ └── include # 插件模块对外提供的接口头文件代码目录
|
||||
│ └── src # 插件模块对外提供的接口源文件代码目录
|
||||
│ ├── memory_plugin # 内存插件模块代码目录
|
||||
│ └── include # 内存插件模块头文件代码目录
|
||||
│ └── src # 内存插件模块源文件代码目录
|
||||
│ └── test # 内存插件模块测试代码目录
|
||||
│ ├── trace_plugin # trace插件模块代码目录
|
||||
│ └── include # trace插件模块头文件代码目录
|
||||
│ └── src # trace插件模块源文件代码目录
|
||||
│ └── test # trace插件模块测试代码目录
|
||||
├── host # 主机侧代码目录
|
||||
│ └── ohosprofiler # 主机侧调优模块代码目录
|
||||
│ └── src # 主机侧调优模块源文件代码目录
|
||||
├── protos # 项目中的proto格式文件的代码目录
|
||||
│ └── innerkits # 对内部子系统暴露的头文件存放目录
|
||||
│ └── builtin # JS应用框架对外暴露JS三方module API接口存放目录
|
||||
├── trace_analyzer # bytrace解析模块的代码目录
|
||||
│ └── include # bytrace解析模块的公共头文件存放目录
|
||||
│ └── src # bytrace解析模块功能源文件存放目录
|
||||
├── interfaces # 项目中接口的代码目录
|
||||
│ └── innerkits # 模块间接口的代码目录
|
||||
│ └── kits # 对外提供接口存放目录
|
||||
```
|
||||
|
||||
## 说明<a name="section2165102016359"></a>
|
||||
|
||||
下面针对设备端对外提供的插件扩展能力进行接口和使用说明。
|
||||
|
||||
### 接口说明<a name="section558917318367"></a>
|
||||
|
||||
下面是设备端插件模块对外提供的接口:
|
||||
|
||||
- PluginModuleCallbacks为插件模块对外提供的回调接口,插件管理模块通过该回调接口列表与每一个插件模块进行交互,每一个新增插件都需要实现该接口列表中的函数。
|
||||
|
||||
**表 1** PluginModuleCallbacks接口列表
|
||||
|
||||
<a name="table214mcpsimp"></a>
|
||||
<table><thead align="left"><tr id="row221mcpsimp"><th class="cellrowborder" valign="top" width="30%" id="mcps1.2.4.1.1"><p id="p223mcpsimp"><a name="p223mcpsimp"></a><a name="p223mcpsimp"></a>接口名</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="30.020000000000003%" id="mcps1.2.4.1.2"><p id="p225mcpsimp"><a name="p225mcpsimp"></a><a name="p225mcpsimp"></a>类型</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="39.98%" id="mcps1.2.4.1.3"><p id="p227mcpsimp"><a name="p227mcpsimp"></a><a name="p227mcpsimp"></a>描述</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row229mcpsimp"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p231mcpsimp"><a name="p231mcpsimp"></a><a name="p231mcpsimp"></a>PluginModuleCallbacks::onPluginSessionStart</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p233mcpsimp"><a name="p233mcpsimp"></a><a name="p233mcpsimp"></a>int (*PluginSessionStartCallback)(const uint8_t* configData, uint32_t configSize);</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><a name="ul1467809165112"></a><a name="ul1467809165112"></a><ul id="ul1467809165112"><li>功能:<p id="p1208131116548"><a name="p1208131116548"></a><a name="p1208131116548"></a>插件会话开始接口,开始插件会话时会被调用,用来下发插件配置</p>
|
||||
</li><li>输入参数:<p id="p104087130518"><a name="p104087130518"></a><a name="p104087130518"></a>configData:配置信息内存块起始地址</p>
|
||||
<p id="p32731219115114"><a name="p32731219115114"></a><a name="p32731219115114"></a>configSize:配置信息内存块字节数</p>
|
||||
</li><li>返回值:<p id="p4892128135110"><a name="p4892128135110"></a><a name="p4892128135110"></a>0:成功</p>
|
||||
<p id="p1621513010517"><a name="p1621513010517"></a><a name="p1621513010517"></a>-1:失败</p>
|
||||
</li></ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row236mcpsimp"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p238mcpsimp"><a name="p238mcpsimp"></a><a name="p238mcpsimp"></a>PluginModuleCallbacks::onPluginReportResult</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p240mcpsimp"><a name="p240mcpsimp"></a><a name="p240mcpsimp"></a>int (*PluginReportResultCallback)(uint8_t* bufferData, uint32_t bufferSize);</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><a name="ul1046263617524"></a><a name="ul1046263617524"></a><ul id="ul1046263617524"><li>功能:<p id="p621321105415"><a name="p621321105415"></a><a name="p621321105415"></a>插件结果上报接口类型,当任务下发后,框架采集任务会周期性调用此接口请求回填数据</p>
|
||||
</li><li>输入参数:<p id="p12796339115211"><a name="p12796339115211"></a><a name="p12796339115211"></a>bufferData: 存放结果的内存缓冲区起始地址</p>
|
||||
<p id="p1163214085219"><a name="p1163214085219"></a><a name="p1163214085219"></a>bufferSize: 存放结果的内存缓冲区的字节数</p>
|
||||
</li><li>返回值:<p id="p114391444135212"><a name="p114391444135212"></a><a name="p114391444135212"></a>大于0:已经填充的内存字节数</p>
|
||||
<p id="p117881419526"><a name="p117881419526"></a><a name="p117881419526"></a>等于0:没有填充任何内容</p>
|
||||
<p id="p7337174625218"><a name="p7337174625218"></a><a name="p7337174625218"></a>小于0:失败</p>
|
||||
</li></ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row243mcpsimp"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p245mcpsimp"><a name="p245mcpsimp"></a><a name="p245mcpsimp"></a>PluginModuleCallbacks::onPluginSessionStop</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p247mcpsimp"><a name="p247mcpsimp"></a><a name="p247mcpsimp"></a>int (*PluginSessionStopCallback)();</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><a name="ul975785275211"></a><a name="ul975785275211"></a><ul id="ul975785275211"><li>功能:<p id="p11471347135914"><a name="p11471347135914"></a><a name="p11471347135914"></a>采集会话结束接口</p>
|
||||
</li><li>返回值:<p id="p4301105945210"><a name="p4301105945210"></a><a name="p4301105945210"></a>0:成功</p>
|
||||
<p id="p145541757125214"><a name="p145541757125214"></a><a name="p145541757125214"></a>-1:失败</p>
|
||||
</li></ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row250mcpsimp"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p252mcpsimp"><a name="p252mcpsimp"></a><a name="p252mcpsimp"></a>PluginModuleCallbacks::onRegisterWriterStruct</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p254mcpsimp"><a name="p254mcpsimp"></a><a name="p254mcpsimp"></a>int (*RegisterWriterStructCallback)(WriterStruct* writer);</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><a name="ul11459712105318"></a><a name="ul11459712105318"></a><ul id="ul11459712105318"><li>功能:<p id="p16725350135912"><a name="p16725350135912"></a><a name="p16725350135912"></a>采集框架注册写数据接口,当插件管理模块向插件注册此接口,插件可以主动调用write句柄,进行写入数据</p>
|
||||
</li><li>输入参数:<p id="p741312324531"><a name="p741312324531"></a><a name="p741312324531"></a>writer 写者指针</p>
|
||||
</li><li>返回值:<p id="p1937282325319"><a name="p1937282325319"></a><a name="p1937282325319"></a>0:成功</p>
|
||||
<p id="p3613421185314"><a name="p3613421185314"></a><a name="p3613421185314"></a>-1:失败</p>
|
||||
</li></ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
- WriterStruct是上面onRegisterWriterStruct接口中的参数,主要实现写数据接口,将插件中采集的数据通过该接口进行写入。
|
||||
|
||||
**表 2** WriterStruct接口列表
|
||||
|
||||
<a name="table1469161115240"></a>
|
||||
<table><thead align="left"><tr id="row124691911182413"><th class="cellrowborder" valign="top" width="30%" id="mcps1.2.4.1.1"><p id="p14469151118247"><a name="p14469151118247"></a><a name="p14469151118247"></a>接口名</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="30.020000000000003%" id="mcps1.2.4.1.2"><p id="p114691119249"><a name="p114691119249"></a><a name="p114691119249"></a>类型</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="39.98%" id="mcps1.2.4.1.3"><p id="p134701611172413"><a name="p134701611172413"></a><a name="p134701611172413"></a>描述</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row5470201102420"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p144702115242"><a name="p144702115242"></a><a name="p144702115242"></a>WriterStruct::write</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p347010119246"><a name="p347010119246"></a><a name="p347010119246"></a>long (*WriteFuncPtr)(WriterStruct* writer, const void* data, size_t size);</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><a name="ul1783144245320"></a><a name="ul1783144245320"></a><ul id="ul1783144245320"><li>功能:<p id="p11675175517597"><a name="p11675175517597"></a><a name="p11675175517597"></a>写接口,将插件中采集的数据通过writer进行写入</p>
|
||||
</li><li>输入参数:<p id="p1812314462537"><a name="p1812314462537"></a><a name="p1812314462537"></a>writer:写者指针</p>
|
||||
<p id="p498224618534"><a name="p498224618534"></a><a name="p498224618534"></a>data:数据缓冲区首字节指针</p>
|
||||
<p id="p368519478533"><a name="p368519478533"></a><a name="p368519478533"></a>size: 数据缓冲区的字节数</p>
|
||||
</li><li>返回值:<p id="p162857527531"><a name="p162857527531"></a><a name="p162857527531"></a>0:成功</p>
|
||||
<p id="p101121150185318"><a name="p101121150185318"></a><a name="p101121150185318"></a>-1:失败</p>
|
||||
</li></ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row84706116243"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p2047081142415"><a name="p2047081142415"></a><a name="p2047081142415"></a>WriterStruct::flush</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p194111838267"><a name="p194111838267"></a><a name="p194111838267"></a>bool (*FlushFuncPtr)(WriterStruct* writer);</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><a name="ul9562185717538"></a><a name="ul9562185717538"></a><ul id="ul9562185717538"><li>功能:<p id="p744185910594"><a name="p744185910594"></a><a name="p744185910594"></a>触发数据上传接口</p>
|
||||
</li><li>输入参数:<p id="p69601111504"><a name="p69601111504"></a><a name="p69601111504"></a>writer:写者指针</p>
|
||||
</li><li>返回值:<p id="p970375016"><a name="p970375016"></a><a name="p970375016"></a>true:成功</p>
|
||||
<p id="p1314495407"><a name="p1314495407"></a><a name="p1314495407"></a>false:失败</p>
|
||||
</li></ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
- 下面是插件模块对外提供的总入口,主要包括表1中的插件模块回调函数以及插件名称、插件模块需要申请的内存大小。
|
||||
|
||||
**表 3** PluginModuleStruct接口列表
|
||||
|
||||
<a name="table14418172393018"></a>
|
||||
<table><thead align="left"><tr id="row14188236300"><th class="cellrowborder" valign="top" width="30%" id="mcps1.2.4.1.1"><p id="p041820239304"><a name="p041820239304"></a><a name="p041820239304"></a>接口名</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="30.020000000000003%" id="mcps1.2.4.1.2"><p id="p34181823153010"><a name="p34181823153010"></a><a name="p34181823153010"></a>类型</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="39.98%" id="mcps1.2.4.1.3"><p id="p10418023123011"><a name="p10418023123011"></a><a name="p10418023123011"></a>描述</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row16418623143016"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p625018817318"><a name="p625018817318"></a><a name="p625018817318"></a>PluginModuleStruct::callbacks</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p162501689312"><a name="p162501689312"></a><a name="p162501689312"></a>PluginModuleCallbacks*</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><p id="p122501085317"><a name="p122501085317"></a><a name="p122501085317"></a>功能:定义插件回调函数列表</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row241952313015"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p325018863113"><a name="p325018863113"></a><a name="p325018863113"></a>PluginModuleStruct::name</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p4250138123112"><a name="p4250138123112"></a><a name="p4250138123112"></a>C style string</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><p id="p425019883115"><a name="p425019883115"></a><a name="p425019883115"></a>功能:定义插件名称</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row49481758173013"><td class="cellrowborder" valign="top" width="30%" headers="mcps1.2.4.1.1 "><p id="p1125010813316"><a name="p1125010813316"></a><a name="p1125010813316"></a>PluginModuleStruct::resultBufferSizeHint</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="30.020000000000003%" headers="mcps1.2.4.1.2 "><p id="p142509810319"><a name="p142509810319"></a><a name="p142509810319"></a>uint32_t</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.2.4.1.3 "><p id="p1525112853115"><a name="p1525112853115"></a><a name="p1525112853115"></a>功能:用于提示插件管理模块调用数据上报接口时使用的内存缓冲区字节数</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### 使用说明<a name="section681316903611"></a>
|
||||
|
||||
下面介绍在设备端基于性能调优框架提供的插件能力,新增一个插件涉及到的关键开发步骤:
|
||||
|
||||
1. 编写proto数据定义文件_plugin\_data.proto_,定义数据源格式,数据源格式决定了插件上报哪些数据:
|
||||
|
||||
```
|
||||
message PluginData {
|
||||
int32 pid = 1;
|
||||
string name = 2;
|
||||
uint64 count1 = 3;
|
||||
uint64 count2 = 4;
|
||||
uint64 count3 = 5;
|
||||
......
|
||||
}
|
||||
```
|
||||
|
||||
2. 编写数据数据源配置文件_plugin\_config.proto_,采集的行为可以根据配置进行变化,可以设置数据源上报间隔等信息:
|
||||
|
||||
```
|
||||
message PluginConfig {
|
||||
int32 pid = 1;
|
||||
bool report_interval = 2;
|
||||
int report_counter_id_1 = 3;
|
||||
int report_counter_id_2 = 4;
|
||||
......
|
||||
}
|
||||
```
|
||||
|
||||
3. 定义PluginModuleCallbacks实现插件回调接口;定义PluginModuleStruct类型的g\_pluginModule全局变量,注册插件信息。
|
||||
|
||||
```
|
||||
static PluginModuleCallbacks callbacks = {
|
||||
PluginSessionStart,
|
||||
PluginReportResult,
|
||||
PluginSessionStop,
|
||||
};
|
||||
PluginModuleStruct g_pluginModule = {&callbacks, "test-plugin", MAX_BUFFER_SIZE};
|
||||
```
|
||||
|
||||
4. 通过PluginSessionStart(名字可以自己定义)实现插件回调接口列表的onPluginSessionStart接口,主要处理插件的开始流程。
|
||||
|
||||
```
|
||||
int PluginSessionStart(const uint8_t* configData, uint32_t configSize)
|
||||
{
|
||||
......
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
5. 通过PluginReportResult(名字可以自己定义)实现插件回调接口列表的onPluginReportResult接口,将插件内部采集的信息通过该接口进行上报:
|
||||
|
||||
```
|
||||
int PluginReportResult(uint8_t* bufferData, uint32_t bufferSize)
|
||||
{
|
||||
......
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
6. 通过PluginSessionStop(名字可以自己定义)实现插件回调接口列表的onPluginSessionStop接口,主要进行插件停止后的操作流程。
|
||||
|
||||
```
|
||||
int PluginSessionStop()
|
||||
{
|
||||
......
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
7. 编写proto gn构建脚本, 生成protobuf源文件,protobuf源文件编译生成目标文件:
|
||||
|
||||
```
|
||||
action("plugin_cpp_gen") {
|
||||
script = "${OHOS_PROFILER_DIR}/build/protoc.sh" //依赖的编译工具链
|
||||
sources = [ //定义的插件相关的proto文件,比如插件配置文件、插件数据对应的proto文件
|
||||
"plugin_data.proto",
|
||||
"plugin_config.proto",
|
||||
]
|
||||
outputs = [ //通过protoc编译生成的结果文件
|
||||
"plugin_data.pb.h",
|
||||
"plugin_data.pb.cc",
|
||||
"plugin_config.pb.h",
|
||||
"plugin_config.pb.cc",
|
||||
]
|
||||
args = [
|
||||
"--cpp_out",
|
||||
"$proto_rel_out_dir",
|
||||
"--proto_path",
|
||||
rebase_path(".", root_build_dir),
|
||||
]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})",
|
||||
]
|
||||
}
|
||||
ohos_source_set("plug_cpp") { //将定义的proto文件生成cpp文件
|
||||
deps = [
|
||||
":plugin_cpp_gen",
|
||||
]
|
||||
public_deps = [
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
]
|
||||
include_dirs = [ "$proto_out_dir" ]
|
||||
sources = [ //目标plug_cpp中包括的源文件
|
||||
"plugin_data.pb.h",
|
||||
"plugin_data.pb.cc",
|
||||
"plugin_config.pb.h",
|
||||
"plugin_config.pb.cc",
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
8. 编写插件GN构建脚本:
|
||||
|
||||
```
|
||||
ohos_shared_library("***plugin") {
|
||||
output_name = "***plugin"
|
||||
sources = [
|
||||
"src/***plugin.cpp", //插件中的源文件
|
||||
]
|
||||
include_dirs = [
|
||||
"../api/include",
|
||||
"${OHOS_PROFILER_DIR}/device/base/include",
|
||||
]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/**:plug_cpp", //上面ohos_source_set中生成的plug_cpp
|
||||
]
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 调测验证:<a name="section35362541215"></a>
|
||||
|
||||
插件动态库生成后,可以自己编写测试代码,通过dlopen加载动态库,并调用上面代码中实现的插件模块回调函数进行验证。
|
||||
|
||||
```
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
void* handle;
|
||||
PluginModuleStruct* memplugin;
|
||||
handle = dlopen("./libplugin.z.so", RTLD_LAZY); //动态打开上面生成的插件动态库
|
||||
if (handle == nullptr) {
|
||||
HILOGD("dlopen err:%s.", dlerror());
|
||||
return 0;
|
||||
}
|
||||
memplugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule"); //获取开发步骤3中定义的g_pluginModule全局变量
|
||||
//check memplugin->callbacks // 通过该指针调用上面开发步骤3中定义的回调函数
|
||||
return 0;
|
||||
```
|
||||
|
||||
## 相关仓<a name="section1293495681320"></a>
|
||||
|
||||
研发工具链子系统
|
||||
|
||||
**developtools\_profiler**
|
||||
|
||||
developtools\_hdc\_standard
|
||||
|
||||
developtools\_bytrace\_standard
|
||||
|
35
build/config.gni
Executable file
35
build/config.gni
Executable file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
OHOS_PROFILER_DIR = get_path_info("..", "abspath")
|
||||
OHOS_PROFILER_3RDPARTY_DIR = get_path_info("../../../third_party/", "abspath")
|
||||
OHOS_PROFILER_3RDPARTY_GRPC_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/grpc"
|
||||
OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR =
|
||||
"${OHOS_PROFILER_3RDPARTY_DIR}/protobuf"
|
||||
OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR =
|
||||
"${OHOS_PROFILER_3RDPARTY_DIR}/googletest"
|
||||
|
||||
OHOS_PROFILER_SUBSYS_NAME = "developtools"
|
||||
OHOS_PROFILER_PART_NAME = "profiler"
|
||||
OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH = "profiler"
|
||||
|
||||
build_l2 = false
|
||||
if (getenv("BUILD_L2") == "true") {
|
||||
build_l2 = true
|
||||
}
|
||||
print("build_l2 =", build_l2)
|
||||
print("OHOS_PROFILER_DIR = ", OHOS_PROFILER_DIR)
|
||||
print("OHOS_PROFILER_3RDPARTY_DIR = ", OHOS_PROFILER_3RDPARTY_DIR)
|
||||
print("OHOS_PROFILER_3RDPARTY_GRPC_DIR = ", OHOS_PROFILER_3RDPARTY_GRPC_DIR)
|
||||
print("OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = ", OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR)
|
||||
print("OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR", OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR)
|
21
build/gcov.sh
Executable file
21
build/gcov.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set -e
|
||||
DIR=$(dirname $(realpath ${BASH_SOURCE[0]}))
|
||||
TOP=$(realpath $DIR/../../..)
|
||||
CLANG_DIR=$TOP/prebuilts/clang/host/linux-x86/clang-r353983c
|
||||
if [ ! -e "$CLANG_DIR" ]; then
|
||||
CLANG_DIR=$TOP/prebuilts/clang/ohos/linux-x86_64/llvm
|
||||
fi
|
||||
$CLANG_DIR/bin/llvm-cov gcov $@
|
38
build/lcov.sh
Executable file
38
build/lcov.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set -e
|
||||
DIR=$(dirname $(realpath ${BASH_SOURCE[0]}))
|
||||
TOP=$(realpath $DIR/../../..)
|
||||
HOST_OUT=$TOP/hos/out/hos-arm/clang_x64
|
||||
if [ ! -e "$HOST_OUT" ]; then
|
||||
HOST_OUT=$TOP/out/ohos-arm-release/clang_x64
|
||||
fi
|
||||
|
||||
|
||||
# collect and convert all gcno and gcda to test.info
|
||||
lcov -c -d $HOST_OUT -o test.info --gcov-tool $DIR/gcov.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Install lcov: sudo apt install lcov"
|
||||
fi
|
||||
|
||||
# filter out system headers
|
||||
lcov -r test.info \
|
||||
'/usr/include/*' \
|
||||
'*/hos/out/*' \
|
||||
'*/hos/third_party/*' \
|
||||
'*/third_party/grpc/*' \
|
||||
-o test.info
|
||||
|
||||
# generate html report
|
||||
genhtml -o html test.info
|
28
build/protoc.sh
Executable file
28
build/protoc.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -e
|
||||
|
||||
THIS_DIR=$(dirname ${BASH_SOURCE[0]})
|
||||
PROJECT_TOP=$(realpath $THIS_DIR/../../..)
|
||||
|
||||
OHOS_X64_OUT=$PROJECT_TOP/$2/clang_x64
|
||||
LIBCXX_X64_OUT=$PROJECT_TOP/$1/ndk/libcxx/linux_x86_64
|
||||
SUBSYS_X64_OUT=$PROJECT_TOP/$2/clang_x64/developtools/developtools
|
||||
PROTOC=$PROJECT_TOP/$2/clang_x64/developtools/developtools/protoc
|
||||
|
||||
PARAMS=$*
|
||||
PARAMS_FILTER="$1 $2"
|
||||
echo "EXEC: LD_LIBRARY_PATH=$LIBCXX_X64_OUT:$SUBSYS_X64_OUT $PROTOC ${PARAMS[@]:${#PARAMS_FILTER}}"
|
||||
LD_LIBRARY_PATH=$LIBCXX_X64_OUT:$SUBSYS_X64_OUT exec $PROTOC ${PARAMS[@]:${#PARAMS_FILTER}}
|
29
build/run.sh
Executable file
29
build/run.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set -e
|
||||
DIR=$(dirname $(realpath ${BASH_SOURCE[0]}))
|
||||
TOP=$(realpath $DIR/../../..)
|
||||
SUBSYS=developtools
|
||||
HOST_OUT=$TOP/hos/out/hos-arm/clang_x64
|
||||
LIB_PATH=$LIB_PATH:$HOST_OUT/devtools/devtools
|
||||
LIB_PATH=$LIB_PATH:$HOST_OUT/$SUBSYS/$SUBSYS
|
||||
LIB_PATH=$LIB_PATH:$HOST_OUT/common/common
|
||||
LIB_PATH=$LIB_PATH:$LD_LIBRARY_PATH
|
||||
|
||||
# remove old coverage data
|
||||
find $HOST_OUT -name '*.gcda' | xargs rm -v
|
||||
|
||||
# run UT executable
|
||||
echo LD_LIBRARY_PATH=$LIB_PATH $@
|
||||
LD_LIBRARY_PATH=$LIB_PATH $@
|
1
device/.clang-format
Symbolic link
1
device/.clang-format
Symbolic link
@ -0,0 +1 @@
|
||||
../tools/.clang-format
|
38
device/BUILD.gn
Executable file
38
device/BUILD.gn
Executable file
@ -0,0 +1,38 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("base/config.gni")
|
||||
|
||||
group("hiprofiler_targets") {
|
||||
deps = [
|
||||
"cmds:hiprofiler_cmd",
|
||||
"plugins/api:hiprofiler_plugins",
|
||||
"plugins/memory_plugin:memdataplugin",
|
||||
"services/profiler_service:hiprofilerd",
|
||||
"services/shared_memory:shared_memory",
|
||||
"plugins/bytrace_plugin:bytraceplugin",
|
||||
]
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"base/test:unittest",
|
||||
"plugins/api/test:unittest",
|
||||
"plugins/memory_plugin/test:unittest",
|
||||
"services/ipc/test:unittest",
|
||||
"services/plugin_service/test:unittest",
|
||||
"services/profiler_service/test:unittest",
|
||||
"services/shared_memory/test:unittest",
|
||||
]
|
||||
}
|
60
device/base/BUILD.gn
Executable file
60
device/base/BUILD.gn
Executable file
@ -0,0 +1,60 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("config.gni")
|
||||
|
||||
# compile options for gcov
|
||||
config("hiprofiler_test_config") {
|
||||
cflags = []
|
||||
if (enable_debuginfo) {
|
||||
cflags += [ "-g" ]
|
||||
}
|
||||
|
||||
if (enable_coverage && current_toolchain == host_toolchain) {
|
||||
cflags += [
|
||||
# clang coverage options:
|
||||
"--coverage",
|
||||
"-mllvm",
|
||||
"-limited-coverage-experimental=true",
|
||||
"-fno-use-cxa-atexit",
|
||||
]
|
||||
ldflags = [ "--coverage" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("hiprofiler_base_config") {
|
||||
include_dirs = [
|
||||
"include",
|
||||
"//utils/native/base/include"
|
||||
]
|
||||
}
|
||||
|
||||
ohos_source_set("hiprofiler_base") {
|
||||
sources = [
|
||||
"src/schedule_task_manager.cpp",
|
||||
]
|
||||
|
||||
public_configs = [
|
||||
":hiprofiler_test_config",
|
||||
":hiprofiler_base_config",
|
||||
]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
if (build_l2) {
|
||||
external_deps = [ "shared_library:libhilog" ]
|
||||
} else {
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
}
|
||||
}
|
||||
}
|
32
device/base/config.gni
Executable file
32
device/base/config.gni
Executable file
@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("../../build/config.gni")
|
||||
|
||||
build_tests = false
|
||||
enable_debuginfo = false
|
||||
enable_coverage = false
|
||||
|
||||
if (getenv("BUILD_UT") == "true") {
|
||||
build_tests = true
|
||||
enable_debuginfo = true
|
||||
enable_coverage = true
|
||||
}
|
||||
|
||||
if (getenv("BUILD_MT") == "true") {
|
||||
build_tests = true
|
||||
enable_debuginfo = true
|
||||
}
|
||||
print("build_tests = ", build_tests)
|
||||
print("enable_debuginfo =", enable_debuginfo)
|
||||
print("enable_coverage =", enable_coverage)
|
131
device/base/include/logging.h
Executable file
131
device/base/include/logging.h
Executable file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#define LOG_TAG ""
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HILOG
|
||||
#include "hilog/log.h"
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "Hiprofiler"
|
||||
|
||||
#else
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <securec.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
static inline long GetTid()
|
||||
{
|
||||
return syscall(SYS_gettid);
|
||||
}
|
||||
|
||||
enum {
|
||||
HILOG_UNKNOWN = 0,
|
||||
HILOG_DEFAULT,
|
||||
HILOG_VERBOSE,
|
||||
HILOG_DEBUG,
|
||||
HILOG_INFO,
|
||||
HILOG_WARN,
|
||||
HILOG_ERROR,
|
||||
HILOG_FATAL,
|
||||
HILOG_SILENT,
|
||||
};
|
||||
|
||||
namespace {
|
||||
constexpr int NS_PER_MS_LOG = 1000 * 1000;
|
||||
}
|
||||
|
||||
static inline std::string GetTimeStr()
|
||||
{
|
||||
char timeStr[64];
|
||||
struct timespec ts;
|
||||
struct tm tmStruct;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
localtime_r(&ts.tv_sec, &tmStruct);
|
||||
size_t used = strftime(timeStr, sizeof(timeStr), "%m-%d %H:%M:%S", &tmStruct);
|
||||
snprintf_s(&timeStr[used], sizeof(timeStr) - used, sizeof(timeStr) - used - 1, ".%03ld",
|
||||
ts.tv_nsec / NS_PER_MS_LOG);
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
typedef const char *ConstCharPtr;
|
||||
|
||||
static inline int HiLogPrintArgs(int prio, ConstCharPtr tag, ConstCharPtr fmt, va_list vargs)
|
||||
{
|
||||
static std::mutex mtx;
|
||||
static std::vector<std::string> prioNames = {"U", " ", "V", "D", "I", "W", "E", "F", "S"};
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
int count =
|
||||
fprintf(stderr, "%s %7d %7ld %5s %s ", GetTimeStr().c_str(), getpid(), GetTid(), prioNames[prio].c_str(), tag);
|
||||
count += vfprintf(stderr, fmt, vargs);
|
||||
count += fprintf(stderr, "\n");
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline int __hilog_log_print(int prio, ConstCharPtr tag, ConstCharPtr fmt, ...)
|
||||
{
|
||||
int count;
|
||||
va_list vargs;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
count = HiLogPrintArgs(prio, tag, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return count;
|
||||
}
|
||||
|
||||
#define HILOG_DEBUG(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
|
||||
#define HILOG_INFO(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_INFO, LOG_TAG, fmt, ##__VA_ARGS__)
|
||||
#define HILOG_WARN(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_WARN, LOG_TAG, fmt, ##__VA_ARGS__)
|
||||
#define HILOG_ERROR(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_ERROR, LOG_TAG, fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
#define STD_PTR(K, T) std::K##_ptr<T>
|
||||
|
||||
#define CHECK_NOTNULL(ptr, retval, fmt, ...) \
|
||||
do { \
|
||||
if (ptr == nullptr) { \
|
||||
HILOG_WARN(LOG_CORE, "CHECK_NOTNULL(%s) in %s:%d FAILED, " fmt, #ptr, __func__, __LINE__, ##__VA_ARGS__); \
|
||||
return retval; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_TRUE(expr, retval, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
HILOG_WARN(LOG_CORE, "CHECK_TRUE(%s) in %s:%d FAILED, " fmt, #expr, __func__, __LINE__, ##__VA_ARGS__); \
|
||||
return retval; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_IF(expr, retval, fmt, ...) \
|
||||
do { \
|
||||
if ((expr)) { \
|
||||
HILOG_WARN(LOG_CORE, fmt, ##__VA_ARGS__); \
|
||||
return retval; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
83
device/base/include/schedule_task_manager.h
Normal file
83
device/base/include/schedule_task_manager.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SCHEDULE_TASK_MANAGER_H
|
||||
#define SCHEDULE_TASK_MANAGER_H
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
class ScheduleTaskManager {
|
||||
public:
|
||||
static ScheduleTaskManager& GetInstance();
|
||||
|
||||
using ms = std::chrono::milliseconds;
|
||||
|
||||
bool ScheduleTask(const std::string& name,
|
||||
const std::function<void(void)>& callback,
|
||||
const std::chrono::milliseconds& repeatInterval);
|
||||
|
||||
bool ScheduleTask(const std::string& name,
|
||||
const std::function<void(void)>& callback,
|
||||
const std::chrono::milliseconds& repeatInterval,
|
||||
std::chrono::milliseconds initialDelay);
|
||||
|
||||
bool UnscheduleTask(const std::string& name);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
ScheduleTaskManager();
|
||||
~ScheduleTaskManager();
|
||||
|
||||
private:
|
||||
using Clock = std::chrono::steady_clock;
|
||||
using TimePoint = std::chrono::time_point<Clock>;
|
||||
|
||||
struct Task {
|
||||
std::string name;
|
||||
std::function<void(void)> callback;
|
||||
std::chrono::milliseconds repeatInterval;
|
||||
std::chrono::milliseconds initialDelay;
|
||||
TimePoint lastRunTime;
|
||||
};
|
||||
using SharedTask = STD_PTR(shared, Task);
|
||||
using WeakTask = STD_PTR(weak, Task);
|
||||
|
||||
static std::chrono::milliseconds NormalizeInterval(std::chrono::milliseconds interval);
|
||||
|
||||
void DumpTask(const SharedTask& task);
|
||||
|
||||
void ScheduleThread();
|
||||
|
||||
bool TakeFront(TimePoint& time, WeakTask& task);
|
||||
|
||||
private:
|
||||
mutable std::mutex taskMutex_;
|
||||
std::condition_variable taskCv_;
|
||||
std::atomic<bool> runScheduleThread_ = true;
|
||||
std::multimap<TimePoint, WeakTask> timeMap_;
|
||||
std::unordered_map<std::string, SharedTask> taskMap_;
|
||||
std::thread scheduleThread_;
|
||||
};
|
||||
|
||||
#endif // !SCHEDULE_TASK_MANAGER_H
|
173
device/base/src/schedule_task_manager.cpp
Normal file
173
device/base/src/schedule_task_manager.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "schedule_task_manager.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
#include "logging.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace {
|
||||
constexpr std::chrono::milliseconds POLL_INTERVAL = std::chrono::milliseconds(5000);
|
||||
constexpr std::chrono::milliseconds MIN_REPEAT_INTERVAL = std::chrono::milliseconds(10);
|
||||
constexpr std::chrono::milliseconds ZERO_INTERVAL = std::chrono::milliseconds(0);
|
||||
} // namespace
|
||||
|
||||
ScheduleTaskManager& ScheduleTaskManager::GetInstance()
|
||||
{
|
||||
static ScheduleTaskManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
ScheduleTaskManager::ScheduleTaskManager()
|
||||
{
|
||||
scheduleThread_ = std::thread(&ScheduleTaskManager::ScheduleThread, this);
|
||||
}
|
||||
|
||||
ScheduleTaskManager::~ScheduleTaskManager()
|
||||
{
|
||||
Shutdown();
|
||||
if (scheduleThread_.joinable()) {
|
||||
scheduleThread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleTaskManager::Shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(taskMutex_);
|
||||
runScheduleThread_ = false;
|
||||
taskCv_.notify_one();
|
||||
}
|
||||
|
||||
std::chrono::milliseconds ScheduleTaskManager::NormalizeInterval(std::chrono::milliseconds interval)
|
||||
{
|
||||
if (interval <= ZERO_INTERVAL) {
|
||||
return ZERO_INTERVAL;
|
||||
}
|
||||
if (interval < MIN_REPEAT_INTERVAL) {
|
||||
return MIN_REPEAT_INTERVAL;
|
||||
}
|
||||
return interval / MIN_REPEAT_INTERVAL * MIN_REPEAT_INTERVAL;
|
||||
}
|
||||
|
||||
bool ScheduleTaskManager::ScheduleTask(const std::string& name,
|
||||
const std::function<void(void)>& callback,
|
||||
const std::chrono::milliseconds& repeatInterval)
|
||||
{
|
||||
return ScheduleTask(name, callback, repeatInterval, repeatInterval);
|
||||
}
|
||||
|
||||
bool ScheduleTaskManager::ScheduleTask(const std::string& name,
|
||||
const std::function<void(void)>& callback,
|
||||
const std::chrono::milliseconds& repeatInterval,
|
||||
std::chrono::milliseconds initialDelay)
|
||||
{
|
||||
auto task = std::make_shared<Task>();
|
||||
|
||||
task->name = name;
|
||||
task->callback = callback;
|
||||
task->initialDelay = initialDelay;
|
||||
task->repeatInterval = NormalizeInterval(repeatInterval);
|
||||
|
||||
std::lock_guard<std::mutex> guard(taskMutex_);
|
||||
if (taskMap_.count(name) > 0) {
|
||||
HILOG_WARN(LOG_CORE, "task name %s already exists!", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
taskMap_[name] = task;
|
||||
timeMap_.insert(std::make_pair(Clock::now() + initialDelay, task));
|
||||
taskCv_.notify_one();
|
||||
|
||||
HILOG_DEBUG(LOG_CORE, "add schedule %s, total: %zu ", name.c_str(), taskMap_.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScheduleTaskManager::UnscheduleTask(const std::string& name)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "del schedule %s, total: %zu", name.c_str(), taskMap_.size());
|
||||
std::unique_lock<std::mutex> lck(taskMutex_);
|
||||
auto it = taskMap_.find(name);
|
||||
if (it != taskMap_.end()) {
|
||||
taskMap_.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScheduleTaskManager::TakeFront(TimePoint& time, WeakTask& task)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(taskMutex_);
|
||||
|
||||
// thread wait until task insert or shutdown
|
||||
while (timeMap_.empty() && runScheduleThread_) {
|
||||
taskCv_.wait_for(lck, POLL_INTERVAL);
|
||||
}
|
||||
|
||||
if (!runScheduleThread_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
time = timeMap_.begin()->first;
|
||||
task = timeMap_.begin()->second;
|
||||
timeMap_.erase(timeMap_.begin());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScheduleTaskManager::DumpTask(const SharedTask& task)
|
||||
{
|
||||
if (task) {
|
||||
long msecs = std::chrono::duration_cast<ms>(task->lastRunTime.time_since_epoch()).count();
|
||||
HILOG_DEBUG(LOG_CORE, "{name = %s, interval = %lld, delay = %lld, lastRun = %ld}",
|
||||
task->name.c_str(), task->repeatInterval.count(), task->initialDelay.count(), msecs);
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleTaskManager::ScheduleThread()
|
||||
{
|
||||
while (true) {
|
||||
// take front task from task queue
|
||||
TimePoint targetTime;
|
||||
WeakTask targetTask;
|
||||
if (!TakeFront(targetTime, targetTask)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// delay to target time
|
||||
auto currentTime = Clock::now();
|
||||
if (targetTime >= currentTime) {
|
||||
std::this_thread::sleep_for(targetTime - currentTime);
|
||||
}
|
||||
|
||||
// promote to shared_ptr
|
||||
auto task = targetTask.lock();
|
||||
DumpTask(task);
|
||||
|
||||
if (task != nullptr) {
|
||||
// call task callback
|
||||
task->callback();
|
||||
task->lastRunTime = currentTime;
|
||||
|
||||
// re-insert task to map if it's a repeat task
|
||||
if (task->repeatInterval.count() != 0) {
|
||||
std::unique_lock<std::mutex> guard(taskMutex_);
|
||||
timeMap_.insert(std::make_pair(targetTime + task->repeatInterval, task));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
device/base/test/BUILD.gn
Executable file
53
device/base/test/BUILD.gn
Executable file
@ -0,0 +1,53 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/test.gni")
|
||||
import("../../base/config.gni")
|
||||
|
||||
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
|
||||
config("module_private_config") {
|
||||
visibility = [":*"]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
}
|
||||
}
|
||||
|
||||
ohos_unittest("hiprofiler_base_ut") {
|
||||
module_out_path = module_output_path
|
||||
deps = [
|
||||
"../:hiprofiler_base",
|
||||
"//third_party/googletest:gtest",
|
||||
]
|
||||
configs = [
|
||||
":module_private_config"
|
||||
]
|
||||
include_dirs = [ "//third_party/googletest/googletest/include/gtest" ]
|
||||
sources = [
|
||||
"unittest/schedule_task_manager_test.cpp",
|
||||
]
|
||||
cflags = [
|
||||
"-Wno-inconsistent-missing-override",
|
||||
"-Dprivate=public", #allow test code access private members
|
||||
]
|
||||
external_deps = [
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
]
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [
|
||||
":hiprofiler_base_ut",
|
||||
]
|
||||
}
|
117
device/base/test/unittest/schedule_task_manager_test.cpp
Executable file
117
device/base/test/unittest/schedule_task_manager_test.cpp
Executable file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
#include <thread>
|
||||
|
||||
#include "schedule_task_manager.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
class ScheduleTaskManagerTest : public testing::Test {
|
||||
protected:
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: base
|
||||
* @tc.desc: Get Instance.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ScheduleTaskManagerTest, GetInstance, TestSize.Level1)
|
||||
{
|
||||
ScheduleTaskManager::GetInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: base
|
||||
* @tc.desc: Single task processing.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ScheduleTaskManagerTest, ScheduleTaskOneshot, TestSize.Level1)
|
||||
{
|
||||
std::atomic<int> count = 0;
|
||||
ScheduleTaskManager::ms initalDelay{10};
|
||||
|
||||
ScheduleTaskManager scheduleTaskManager;
|
||||
EXPECT_TRUE(scheduleTaskManager.ScheduleTask(
|
||||
"task-1", [&]() { count++; }, ScheduleTaskManager::ms{0}, initalDelay));
|
||||
|
||||
std::this_thread::sleep_for(initalDelay + initalDelay);
|
||||
EXPECT_EQ(count.load(), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: base
|
||||
* @tc.desc: Repetitive task processing.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ScheduleTaskManagerTest, ScheduleTaskRepeated, TestSize.Level1)
|
||||
{
|
||||
std::atomic<int> count = 0;
|
||||
constexpr int cnt = 5;
|
||||
|
||||
ScheduleTaskManager::ms repeatInterval{100};
|
||||
ScheduleTaskManager::ms initalDelay{10};
|
||||
|
||||
ScheduleTaskManager scheduleTaskManager;
|
||||
EXPECT_TRUE(scheduleTaskManager.ScheduleTask(
|
||||
"task-2", [&]() { count++; }, repeatInterval, initalDelay));
|
||||
|
||||
int expected = 0;
|
||||
std::this_thread::sleep_for(initalDelay + initalDelay);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
expected++;
|
||||
EXPECT_EQ(count.load(), expected);
|
||||
std::this_thread::sleep_for(repeatInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: base
|
||||
* @tc.desc: Unschedule Task.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ScheduleTaskManagerTest, UnscheduleTask, TestSize.Level1)
|
||||
{
|
||||
std::atomic<int> count = 0;
|
||||
constexpr int cnt = 5;
|
||||
|
||||
std::string taskName = "task-3";
|
||||
ScheduleTaskManager::ms repeatInterval{100};
|
||||
ScheduleTaskManager::ms initalDelay{10};
|
||||
|
||||
ScheduleTaskManager scheduleTaskManager;
|
||||
EXPECT_TRUE(scheduleTaskManager.ScheduleTask(
|
||||
taskName, [&]() { count++; }, repeatInterval));
|
||||
|
||||
int expected = 0;
|
||||
std::this_thread::sleep_for(initalDelay);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
std::this_thread::sleep_for(repeatInterval);
|
||||
expected++;
|
||||
EXPECT_EQ(count.load(), expected);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(scheduleTaskManager.UnscheduleTask(taskName));
|
||||
scheduleTaskManager.Shutdown();
|
||||
|
||||
EXPECT_EQ(count.load(), expected);
|
||||
}
|
||||
} // namespace
|
41
device/cmds/BUILD.gn
Executable file
41
device/cmds/BUILD.gn
Executable file
@ -0,0 +1,41 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../base/config.gni")
|
||||
|
||||
ohos_source_set("command_line") {
|
||||
sources = [
|
||||
"src/command_line.cpp",
|
||||
"src/command_param.cpp",
|
||||
"src/command_param_switch.cpp",
|
||||
"src/command_param_text.cpp",
|
||||
]
|
||||
include_dirs = [ "include" ]
|
||||
}
|
||||
ohos_executable("hiprofiler_cmd") {
|
||||
sources = [
|
||||
"src/main.cpp",
|
||||
]
|
||||
include_dirs = [ "include" ]
|
||||
deps = [
|
||||
":command_line",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:profiler_services_proto",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:service_types_proto",
|
||||
]
|
||||
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
76
device/cmds/include/command_line.h
Normal file
76
device/cmds/include/command_line.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_LINE_H
|
||||
#define COMMAND_LINE_H
|
||||
|
||||
#include "command_param.h"
|
||||
#include "command_param_switch.h"
|
||||
#include "command_param_text.h"
|
||||
#include <vector>
|
||||
|
||||
#ifdef VT100_ENABLE
|
||||
#define VT100_RED "\033[31m"
|
||||
#define VT100_GREEN "\033[32m"
|
||||
#define VT100_YELLOW "\033[33m"
|
||||
#define VT100_BLUE "\033[34m"
|
||||
#define VT100_PURPLE "\033[35m"
|
||||
#define VT100_CYAN "\033[36m"
|
||||
#define VT100_WHITE "\033[37m"
|
||||
|
||||
#define VT100_CLOSE "\033[0m"
|
||||
#define VT100_BRIGHT "\033[1m"
|
||||
#define VT100_UNDERLINE "\033[4m"
|
||||
#define VT100_FLASH "\033[5m"
|
||||
#else
|
||||
#define VT100_RED ""
|
||||
#define VT100_GREEN ""
|
||||
#define VT100_YELLOW ""
|
||||
#define VT100_BLUE ""
|
||||
#define VT100_PURPLE ""
|
||||
#define VT100_CYAN ""
|
||||
#define VT100_WHITE ""
|
||||
|
||||
#define VT100_CLOSE ""
|
||||
#define VT100_BRIGHT ""
|
||||
#define VT100_UNDERLINE ""
|
||||
#define VT100_FLASH ""
|
||||
#endif
|
||||
|
||||
class CommandLine {
|
||||
public:
|
||||
static CommandLine& GetInstance();
|
||||
|
||||
int AnalyzeParam(std::vector<std::string> argv);
|
||||
|
||||
void AddParamSwitch(const std::string& filter1, const std::string& filter2, bool &pbool, const std::string& desc);
|
||||
void AddParamText(const std::string& filter1,
|
||||
const std::string& filter2,
|
||||
std::string& pstr,
|
||||
const std::string& desc);
|
||||
|
||||
void PrintHelp();
|
||||
|
||||
private:
|
||||
CommandLine();
|
||||
~CommandLine();
|
||||
|
||||
int paramIdx_;
|
||||
std::map<uint32_t, std::shared_ptr<CommandParam>> commandParams_;
|
||||
|
||||
int CheckParam(const std::string& s1, const std::string& s2);
|
||||
};
|
||||
|
||||
#endif
|
37
device/cmds/include/command_param.h
Executable file
37
device/cmds/include/command_param.h
Executable file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_PARAM_H
|
||||
#define COMMAND_PARAM_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
enum PARAM_TYPE { PARAM_TYPE_SWITCH, PARAM_TYPE_TEXT };
|
||||
|
||||
class CommandParam {
|
||||
public:
|
||||
enum PARAM_TYPE paramType_;
|
||||
std::string sDescriptor_;
|
||||
|
||||
std::list<std::string> paramFilter_;
|
||||
|
||||
void AddFilter(const std::string& filterName);
|
||||
bool IsInFilter(const std::string& filterName);
|
||||
};
|
||||
|
||||
#endif
|
31
device/cmds/include/command_param_switch.h
Executable file
31
device/cmds/include/command_param_switch.h
Executable file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_SWITCH_H
|
||||
#define COMMAND_SWITCH_H
|
||||
|
||||
#include "command_param.h"
|
||||
|
||||
class CommandParamSwitch : public CommandParam {
|
||||
public:
|
||||
CommandParamSwitch(bool& value);
|
||||
~CommandParamSwitch() {}
|
||||
void SetValue(bool value);
|
||||
|
||||
private:
|
||||
bool& boolSwitch_;
|
||||
};
|
||||
|
||||
#endif
|
31
device/cmds/include/command_param_text.h
Executable file
31
device/cmds/include/command_param_text.h
Executable file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_TEXT_H
|
||||
#define COMMAND_TEXT_H
|
||||
|
||||
#include "command_param.h"
|
||||
|
||||
class CommandParamText : public CommandParam {
|
||||
public:
|
||||
CommandParamText(std::string& s);
|
||||
~CommandParamText() {}
|
||||
void SetValue(const std::string& s);
|
||||
|
||||
private:
|
||||
std::string& stringText_;
|
||||
};
|
||||
|
||||
#endif
|
144
device/cmds/src/command_line.cpp
Normal file
144
device/cmds/src/command_line.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "command_line.h"
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include "command_param.h"
|
||||
#include "command_param_switch.h"
|
||||
#include "command_param_text.h"
|
||||
|
||||
CommandLine& CommandLine::GetInstance()
|
||||
{
|
||||
static CommandLine commandLine;
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
CommandLine::CommandLine()
|
||||
{
|
||||
paramIdx_ = 0;
|
||||
}
|
||||
CommandLine::~CommandLine() {}
|
||||
|
||||
void CommandLine::AddParamText(const std::string& filter1,
|
||||
const std::string& filter2,
|
||||
std::string& pstr,
|
||||
const std::string& desc)
|
||||
{
|
||||
auto pret = std::make_shared<CommandParamText>(pstr);
|
||||
if (!filter1.empty()) {
|
||||
pret->AddFilter(filter1);
|
||||
}
|
||||
if (!filter2.empty()) {
|
||||
pret->AddFilter(filter2);
|
||||
}
|
||||
pret->paramType_ = PARAM_TYPE_TEXT;
|
||||
pret->sDescriptor_ = desc;
|
||||
commandParams_[paramIdx_++] = pret;
|
||||
}
|
||||
|
||||
void CommandLine::AddParamSwitch(const std::string& filter1,
|
||||
const std::string& filter2,
|
||||
bool &pbool,
|
||||
const std::string& desc)
|
||||
{
|
||||
auto pret = std::make_shared<CommandParamSwitch>(pbool);
|
||||
if (!filter1.empty()) {
|
||||
pret->AddFilter(filter1);
|
||||
}
|
||||
if (!filter2.empty()) {
|
||||
pret->AddFilter(filter2);
|
||||
}
|
||||
pret->paramType_ = PARAM_TYPE_SWITCH;
|
||||
pret->sDescriptor_ = desc;
|
||||
commandParams_[paramIdx_++] = pret;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const int USED_PARAM_ONE = 1;
|
||||
const int USED_PARAM_TWO = 2;
|
||||
const int USED_PARAM_ERR = 99999;
|
||||
|
||||
const int MAX_TAB_COUNT = 2;
|
||||
} // namespace
|
||||
|
||||
int CommandLine::CheckParam(const std::string& s1, const std::string& s2)
|
||||
{
|
||||
for (auto it = commandParams_.begin(); it != commandParams_.end(); ++it) {
|
||||
auto p = it->second;
|
||||
if (!p->IsInFilter(s1)) {
|
||||
continue;
|
||||
}
|
||||
switch (p->paramType_) {
|
||||
case PARAM_TYPE_SWITCH: {
|
||||
CommandParamSwitch* pswitch = (CommandParamSwitch*)p.get();
|
||||
pswitch->SetValue(true);
|
||||
return USED_PARAM_ONE;
|
||||
} break;
|
||||
case PARAM_TYPE_TEXT: {
|
||||
CommandParamText* ptext = (CommandParamText*)p.get();
|
||||
if (s2 != "") {
|
||||
ptext->SetValue(s2);
|
||||
return USED_PARAM_TWO;
|
||||
}
|
||||
printf("%s lost content\n", s1.c_str());
|
||||
return USED_PARAM_ERR;
|
||||
} break;
|
||||
default:
|
||||
printf("unknown type\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("unknown param '%s'\n", s1.c_str());
|
||||
return USED_PARAM_ERR;
|
||||
}
|
||||
int CommandLine::AnalyzeParam(std::vector<std::string> argv)
|
||||
{
|
||||
size_t i = 1;
|
||||
while (i < argv.size()) {
|
||||
i += CheckParam(argv[i], (i + 1 < argv.size()) ? argv[i + 1] : "");
|
||||
}
|
||||
if (i >= USED_PARAM_ERR) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CommandLine::PrintHelp()
|
||||
{
|
||||
printf("%shelp :\n", VT100_RED);
|
||||
for (auto it = commandParams_.begin(); it != commandParams_.end(); ++it) {
|
||||
auto p = it->second;
|
||||
|
||||
int i = 0;
|
||||
for (std::string temp : p->paramFilter_) {
|
||||
i++;
|
||||
if (i == 1) {
|
||||
printf(" %-16s", temp.c_str());
|
||||
} else {
|
||||
printf(" %-2s", temp.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < MAX_TAB_COUNT; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf(" : %s\n", p->sDescriptor_.c_str());
|
||||
}
|
||||
printf("%s", VT100_CLOSE);
|
||||
}
|
32
device/cmds/src/command_param.cpp
Executable file
32
device/cmds/src/command_param.cpp
Executable file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "command_param.h"
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
void CommandParam::AddFilter(const std::string& filterName)
|
||||
{
|
||||
if (IsInFilter(filterName)) {
|
||||
return;
|
||||
}
|
||||
paramFilter_.push_back(filterName);
|
||||
}
|
||||
bool CommandParam::IsInFilter(const std::string& filterName)
|
||||
{
|
||||
return std::any_of(paramFilter_.begin(), paramFilter_.end(),
|
||||
[filterName](std::string s) { return s == filterName; });
|
||||
}
|
23
device/cmds/src/command_param_switch.cpp
Executable file
23
device/cmds/src/command_param_switch.cpp
Executable file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "command_param_switch.h"
|
||||
|
||||
CommandParamSwitch::CommandParamSwitch(bool& value) : boolSwitch_(value) {}
|
||||
|
||||
void CommandParamSwitch::SetValue(bool value)
|
||||
{
|
||||
boolSwitch_ = value;
|
||||
}
|
22
device/cmds/src/command_param_text.cpp
Executable file
22
device/cmds/src/command_param_text.cpp
Executable file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "command_param_text.h"
|
||||
|
||||
CommandParamText::CommandParamText(std::string& s) : stringText_(s) {}
|
||||
void CommandParamText::SetValue(const std::string& s)
|
||||
{
|
||||
stringText_ = s;
|
||||
}
|
242
device/cmds/src/main.cpp
Normal file
242
device/cmds/src/main.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "command_line.h"
|
||||
#include "profiler_service.grpc.pb.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace {
|
||||
const int ADDR_BUFFER_SIZE = 128;
|
||||
const int MS_PER_S = 1000;
|
||||
|
||||
std::string GetIpAddr()
|
||||
{
|
||||
char addressBuffer[ADDR_BUFFER_SIZE] = {0};
|
||||
struct ifaddrs* ifAddrStruct = nullptr;
|
||||
void* tmpAddrPtr = nullptr;
|
||||
|
||||
getifaddrs(&ifAddrStruct);
|
||||
|
||||
while (ifAddrStruct != nullptr) {
|
||||
if (ifAddrStruct->ifa_addr->sa_family == AF_INET) {
|
||||
// is a valid IP4 Address
|
||||
tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
|
||||
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
||||
if (strcmp(addressBuffer, "127.0.0.1") != 0) {
|
||||
return addressBuffer;
|
||||
}
|
||||
} else if (ifAddrStruct->ifa_addr->sa_family == AF_INET6) { // check it is IP6
|
||||
// is a valid IP6 Address
|
||||
tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
|
||||
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
}
|
||||
ifAddrStruct = ifAddrStruct->ifa_next;
|
||||
}
|
||||
return addressBuffer;
|
||||
}
|
||||
|
||||
std::string ReadFileToString(const std::string& fileName)
|
||||
{
|
||||
std::ifstream inputString(fileName, std::ios::in);
|
||||
if (!inputString) {
|
||||
printf("can't open %s\n", fileName.c_str());
|
||||
return "";
|
||||
}
|
||||
std::string content(std::istreambuf_iterator<char> {inputString}, std::istreambuf_iterator<char> {});
|
||||
return content;
|
||||
}
|
||||
|
||||
std::string ReadConfigContent(const std::string& configFileName)
|
||||
{
|
||||
std::string content;
|
||||
if (configFileName == "-") { // Read configuration information from standard input
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
content += line + "\n";
|
||||
}
|
||||
} else {
|
||||
content = ReadFileToString(configFileName);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
std::unique_ptr<CreateSessionRequest> MakeCreateRequest(const std::string& configFileName,
|
||||
const std::string& keepSecond, const std::string& outputFileName)
|
||||
{
|
||||
auto request = std::make_unique<CreateSessionRequest>();
|
||||
auto sessionConfig = request->mutable_session_config();
|
||||
if (!request || !sessionConfig) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string content = ReadConfigContent(configFileName);
|
||||
if (content.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!google::protobuf::TextFormat::ParseFromString(content, request.get())) {
|
||||
printf("config file [%s] format error!\n", configFileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
request->set_request_id(0);
|
||||
if (!keepSecond.empty()) {
|
||||
int ks = std::stoi(keepSecond);
|
||||
if (ks > 0) {
|
||||
sessionConfig->set_sample_duration(ks * MS_PER_S);
|
||||
}
|
||||
}
|
||||
if (!outputFileName.empty()) {
|
||||
sessionConfig->set_result_file(outputFileName);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
std::unique_ptr<IProfilerService::Stub> GetProfilerServiceStub()
|
||||
{
|
||||
auto grpcChannel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials());
|
||||
if (grpcChannel == nullptr) {
|
||||
printf("FAIL\nCreate gRPC channel failed!\n");
|
||||
return nullptr;
|
||||
}
|
||||
return IProfilerService::NewStub(grpcChannel);
|
||||
}
|
||||
|
||||
uint32_t CreateSession(const std::string& configFileName,
|
||||
const std::string& keepSecond, const std::string& outputFileName)
|
||||
{
|
||||
auto profilerStub = GetProfilerServiceStub();
|
||||
if (profilerStub == nullptr) {
|
||||
printf("FAIL\nGet profiler service stub failed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto request = MakeCreateRequest(configFileName, keepSecond, outputFileName);
|
||||
if (!request) {
|
||||
printf("FAIL\nMakeCreateRequest failed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
CreateSessionResponse createResponse;
|
||||
grpc::ClientContext createSessionContext;
|
||||
grpc::Status status = profilerStub->CreateSession(&createSessionContext, *request, &createResponse);
|
||||
if (!status.ok()) {
|
||||
printf("FAIL\nCreateSession FAIL\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return createResponse.session_id();
|
||||
}
|
||||
|
||||
bool StartSession(const std::string& configFileName,
|
||||
const std::string& keepSecond, const std::string& outputFileName)
|
||||
{
|
||||
uint32_t sessionId = CreateSession(configFileName, keepSecond, outputFileName);
|
||||
auto profilerStub = GetProfilerServiceStub();
|
||||
if (profilerStub == nullptr) {
|
||||
printf("FAIL\nGet profiler service stub failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
StartSessionRequest startRequest;
|
||||
StartSessionResponse startResponse;
|
||||
startRequest.set_request_id(0);
|
||||
startRequest.set_session_id(sessionId);
|
||||
grpc::ClientContext startSessionContext;
|
||||
grpc::Status status = profilerStub->StartSession(&startSessionContext, startRequest, &startResponse);
|
||||
if (!status.ok()) {
|
||||
printf("FAIL\nStartSession FAIL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
CommandLine* pCmdLine = &CommandLine::GetInstance();
|
||||
|
||||
bool isGetGrpcAddr = false;
|
||||
pCmdLine->AddParamSwitch("--getport", "-q", isGetGrpcAddr, "get grpc address");
|
||||
|
||||
std::string configFileName;
|
||||
pCmdLine->AddParamText("--config", "-c", configFileName, "start trace by config file");
|
||||
|
||||
std::string traceKeepSecond;
|
||||
pCmdLine->AddParamText("--time", "-t", traceKeepSecond, "trace time");
|
||||
|
||||
std::string outputFileName;
|
||||
pCmdLine->AddParamText("--out", "-o", outputFileName, "output file name");
|
||||
|
||||
bool isHelp = false;
|
||||
pCmdLine->AddParamSwitch("--help", "-h", isHelp, "make some help");
|
||||
|
||||
bool isBackground = false;
|
||||
pCmdLine->AddParamSwitch("--background", "-d", isBackground, "run in background");
|
||||
|
||||
std::vector<std::string> argvVector;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
argvVector.push_back(argv[i]);
|
||||
}
|
||||
if (argc < 1 || pCmdLine->AnalyzeParam(argvVector) < 0 || isHelp) {
|
||||
pCmdLine->PrintHelp();
|
||||
exit(0);
|
||||
}
|
||||
if (isGetGrpcAddr) {
|
||||
auto profilerStub = GetProfilerServiceStub();
|
||||
if (profilerStub == nullptr) {
|
||||
printf("FAIL\nGet profiler service stub failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
GetCapabilitiesRequest request;
|
||||
GetCapabilitiesResponse response;
|
||||
request.set_request_id(0);
|
||||
|
||||
grpc::ClientContext context;
|
||||
grpc::Status status = profilerStub->GetCapabilities(&context, request, &response);
|
||||
if (!status.ok()) {
|
||||
printf("FAIL\nService not started\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("OK\nip:%s\nport:50051\n", GetIpAddr().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!configFileName.empty()) {
|
||||
// Read the configFileName,convert to protobuf object,structure 'CreateSession',Send 'StartSession' command to
|
||||
// profilerd
|
||||
if (StartSession(configFileName, traceKeepSecond, outputFileName)) {
|
||||
printf("OK\ntracing...\n");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
29
device/format-code.sh
Executable file
29
device/format-code.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
DIR=$(dirname $(realpath ${BASH_SOURCE[0]}))
|
||||
TOP=$(realpath $DIR/../../..)
|
||||
CLANG_DIR=$TOP/prebuilts/clang/ohos/linux-x86_64/llvm/bin
|
||||
GN_DIR=$TOP/prebuilts/build-tools/linux-x86/bin
|
||||
|
||||
export PATH=$CLANG_DIR:$GN_DIR:$PATH
|
||||
echo "formatting C/C++ code ..."
|
||||
find $@ -name '*.h' -o -name '*.cpp' | xargs clang-format --verbose -i
|
||||
|
||||
echo "formatting GN code ..."
|
||||
find $@ -name '*.gn' -o -name '*.gni' | xargs gn format
|
81
device/plugins/api/BUILD.gn
Executable file
81
device/plugins/api/BUILD.gn
Executable file
@ -0,0 +1,81 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../../base/config.gni")
|
||||
|
||||
config("hiprofiler_plugins_config") {
|
||||
include_dirs = [
|
||||
"./include",
|
||||
"./src",
|
||||
"../../base/include/",
|
||||
"${OHOS_PROFILER_DIR}/device/services/ipc/include",
|
||||
"${OHOS_PROFILER_DIR}/device/services/shared_memory/include",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
]
|
||||
cflags = [ "-pthread" ]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
cflags += [ "-DHAVE_HILOG" ]
|
||||
}
|
||||
}
|
||||
|
||||
ohos_source_set("plugins_sources") {
|
||||
include_dirs = [
|
||||
"./include",
|
||||
"../../base/include/",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
"//utils/native/base/include",
|
||||
]
|
||||
sources = [
|
||||
"src/buffer_writer.cpp",
|
||||
"src/command_poller.cpp",
|
||||
"src/plugin_module.cpp",
|
||||
"src/plugin_manager.cpp",
|
||||
"src/plugin_watcher.cpp",
|
||||
"src/writer_adapter.cpp",
|
||||
]
|
||||
public_deps = [
|
||||
"${OHOS_PROFILER_DIR}/device/services/shared_memory:shared_memory",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:plugin_services_proto",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:service_types_proto",
|
||||
"../../base:hiprofiler_base",
|
||||
"//utils/native/base:utilsbase",
|
||||
]
|
||||
public_configs = [ ":hiprofiler_plugins_config" ]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
if (build_l2) {
|
||||
external_deps = [ "shared_library:libhilog" ]
|
||||
} else {
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ohos_executable("hiprofiler_plugins") {
|
||||
deps = [
|
||||
":plugins_sources",
|
||||
]
|
||||
sources = [
|
||||
"src/main.cpp",
|
||||
]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
if (build_l2) {
|
||||
external_deps = [ "shared_library:libhilog" ]
|
||||
} else {
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
}
|
||||
}
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
28
device/plugins/api/include/writer.h
Executable file
28
device/plugins/api/include/writer.h
Executable file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WRITER_H
|
||||
#define WRITER_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
class Writer {
|
||||
public:
|
||||
virtual ~Writer() {}
|
||||
virtual long Write(const void* data, size_t size) = 0;
|
||||
virtual bool Flush() = 0;
|
||||
};
|
||||
|
||||
#endif // !WRITER_H
|
64
device/plugins/api/src/buffer_writer.cpp
Normal file
64
device/plugins/api/src/buffer_writer.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "buffer_writer.h"
|
||||
#include "command_poller.h"
|
||||
#include "logging.h"
|
||||
#include "plugin_service_types.pb.h"
|
||||
#include "share_memory_allocator.h"
|
||||
|
||||
BufferWriter::BufferWriter(std::string name,
|
||||
uint32_t size,
|
||||
int fd,
|
||||
const CommandPollerPtr& cp,
|
||||
uint32_t pluginId)
|
||||
: pluginName_(name)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "CreateMemoryBlockRemote %s %d %d", name.c_str(), size, fd);
|
||||
shareMemoryBlock_ = ShareMemoryAllocator::GetInstance().CreateMemoryBlockRemote(name, size, fd);
|
||||
if (shareMemoryBlock_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "shareMemoryBlock_ == nullptr=");
|
||||
}
|
||||
commandPoller_ = cp;
|
||||
pluginId_ = pluginId;
|
||||
}
|
||||
|
||||
BufferWriter::~BufferWriter()
|
||||
{
|
||||
ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockRemote(pluginName_);
|
||||
}
|
||||
|
||||
long BufferWriter::Write(const void* data, size_t size)
|
||||
{
|
||||
if (shareMemoryBlock_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "BufferWriter Write %zu", size);
|
||||
return shareMemoryBlock_->PutRaw(reinterpret_cast<const int8_t*>(data), static_cast<uint32_t>(size));
|
||||
}
|
||||
|
||||
bool BufferWriter::WriteProtobuf(google::protobuf::Message& pmsg)
|
||||
{
|
||||
if (shareMemoryBlock_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "BufferWriter Write %zu", pmsg.ByteSizeLong());
|
||||
return shareMemoryBlock_->PutProtobuf(pmsg);
|
||||
}
|
||||
|
||||
bool BufferWriter::Flush()
|
||||
{
|
||||
return true;
|
||||
}
|
44
device/plugins/api/src/buffer_writer.h
Executable file
44
device/plugins/api/src/buffer_writer.h
Executable file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BUFFER_WRITER_H
|
||||
#define BUFFER_WRITER_H
|
||||
|
||||
#include <memory>
|
||||
#include "plugin_module_api.h"
|
||||
#include "share_memory_allocator.h"
|
||||
#include "writer.h"
|
||||
|
||||
class CommandPoller;
|
||||
|
||||
using CommandPollerPtr = STD_PTR(shared, CommandPoller);
|
||||
|
||||
class BufferWriter : public Writer {
|
||||
public:
|
||||
BufferWriter(std::string name, uint32_t size, int fd, const CommandPollerPtr& cp, uint32_t pluginId);
|
||||
~BufferWriter();
|
||||
long Write(const void* data, size_t size) override;
|
||||
bool Flush() override;
|
||||
|
||||
bool WriteProtobuf(google::protobuf::Message& pmsg);
|
||||
|
||||
private:
|
||||
std::string pluginName_;
|
||||
std::shared_ptr<ShareMemoryBlock> shareMemoryBlock_;
|
||||
CommandPollerPtr commandPoller_;
|
||||
uint32_t pluginId_;
|
||||
};
|
||||
|
||||
#endif // BUFFER_WRITER_H
|
169
device/plugins/api/src/command_poller.cpp
Normal file
169
device/plugins/api/src/command_poller.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "command_poller.h"
|
||||
#include "buffer_writer.h"
|
||||
#include "plugin_manager.h"
|
||||
#include "socket_context.h"
|
||||
|
||||
CommandPoller::CommandPoller(const PluginManagerPtr& p)
|
||||
: requestIdAutoIncrease_(1), pluginManager_(p)
|
||||
{
|
||||
Connect(DEFAULT_UNIX_SOCKET_PATH);
|
||||
}
|
||||
|
||||
CommandPoller::~CommandPoller() {}
|
||||
|
||||
uint32_t CommandPoller::GetRequestId()
|
||||
{
|
||||
return requestIdAutoIncrease_++;
|
||||
}
|
||||
|
||||
bool CommandPoller::OnCreateSessionCmd(const CreateSessionCmd& cmd, SocketContext& context) const
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd PROC");
|
||||
uint32_t bufferSize = cmd.buffer_sizes(0);
|
||||
ProfilerPluginConfig config = cmd.plugin_configs(0);
|
||||
std::vector<ProfilerPluginConfig> configVec;
|
||||
configVec.push_back(config);
|
||||
|
||||
auto pluginManager = pluginManager_.lock(); // promote to shared_ptr
|
||||
CHECK_NOTNULL(pluginManager, false, "promote FAILED!");
|
||||
|
||||
if (!pluginManager->LoadPlugin(config.name())) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd FAIL 1");
|
||||
return false;
|
||||
}
|
||||
int fd = -1;
|
||||
if (bufferSize != 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd bufferSize = %d", bufferSize);
|
||||
fd = context.ReceiveFileDiscriptor();
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd fd = %d", fd);
|
||||
}
|
||||
if (!pluginManager->CreateWriter(config.name(), bufferSize, fd)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd CreateWriter FAIL");
|
||||
return false;
|
||||
}
|
||||
if (!pluginManager->CreatePluginSession(configVec)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd CreatePluginSession FAIL");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandPoller::OnDestroySessionCmd(const DestroySessionCmd& cmd) const
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "OnDestroySessionCmd PROC");
|
||||
uint32_t pluginId = cmd.plugin_ids(0);
|
||||
std::vector<uint32_t> pluginIdVec;
|
||||
pluginIdVec.push_back(pluginId);
|
||||
|
||||
auto pluginManager = pluginManager_.lock(); // promote to shared_ptr
|
||||
CHECK_NOTNULL(pluginManager, false, "promote FAILED!");
|
||||
|
||||
if (!pluginManager->DestroyPluginSession(pluginIdVec)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnDestroySessionCmd DestroyPluginSession FAIL");
|
||||
return false;
|
||||
}
|
||||
if (!pluginManager->ResetWriter(pluginId)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnDestroySessionCmd ResetWriter FAIL");
|
||||
return false;
|
||||
}
|
||||
if (!pluginManager->UnloadPlugin(pluginId)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnDestroySessionCmd UnloadPlugin FAIL");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "OnDestroySessionCmd OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandPoller::OnStartSessionCmd(const StartSessionCmd& cmd) const
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "OnStartSessionCmd PROC");
|
||||
std::vector<uint32_t> pluginIds;
|
||||
pluginIds.push_back(cmd.plugin_ids(0));
|
||||
std::vector<ProfilerPluginConfig> configVec;
|
||||
configVec.push_back(cmd.plugin_configs(0));
|
||||
|
||||
auto pluginManager = pluginManager_.lock(); // promote to shared_ptr
|
||||
CHECK_NOTNULL(pluginManager, false, "promote FAILED!");
|
||||
|
||||
if (!pluginManager->StartPluginSession(pluginIds, configVec)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnStartSessionCmd FAIL");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "OnStartSessionCmd OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandPoller::OnStopSessionCmd(const StopSessionCmd& cmd) const
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "OnStopSessionCmd PROC");
|
||||
std::vector<uint32_t> pluginIds;
|
||||
pluginIds.push_back(cmd.plugin_ids(0));
|
||||
|
||||
auto pluginManager = pluginManager_.lock(); // promote to shared_ptr
|
||||
CHECK_NOTNULL(pluginManager, false, "promote FAILED!");
|
||||
|
||||
if (!pluginManager->StopPluginSession(pluginIds)) {
|
||||
HILOG_DEBUG(LOG_CORE, "OnStopSessionCmd FAIL");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "OnStopSessionCmd OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandPoller::OnGetCommandResponse(SocketContext& context, ::GetCommandResponse& response)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "OnGetCommandResponse");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
NotifyResultRequest nrr;
|
||||
nrr.set_request_id(1);
|
||||
nrr.set_command_id(response.command_id());
|
||||
PluginResult* pr = nrr.add_result();
|
||||
ProfilerPluginState* status = pr->mutable_status();
|
||||
|
||||
if (response.has_create_session_cmd()) {
|
||||
if (OnCreateSessionCmd(response.create_session_cmd(), context)) {
|
||||
status->set_state(ProfilerPluginState::LOADED);
|
||||
} else {
|
||||
status->set_state(ProfilerPluginState::REGISTERED);
|
||||
}
|
||||
} else if (response.has_destroy_session_cmd()) {
|
||||
if (OnDestroySessionCmd(response.destroy_session_cmd())) {
|
||||
status->set_state(ProfilerPluginState::REGISTERED);
|
||||
} else {
|
||||
status->set_state(ProfilerPluginState::LOADED);
|
||||
}
|
||||
} else if (response.has_start_session_cmd()) {
|
||||
if (OnStartSessionCmd(response.start_session_cmd())) {
|
||||
status->set_state(ProfilerPluginState::IN_SESSION);
|
||||
} else {
|
||||
status->set_state(ProfilerPluginState::LOADED);
|
||||
}
|
||||
} else if (response.has_stop_session_cmd()) {
|
||||
if (OnStopSessionCmd(response.stop_session_cmd())) {
|
||||
status->set_state(ProfilerPluginState::LOADED);
|
||||
} else {
|
||||
status->set_state(ProfilerPluginState::IN_SESSION);
|
||||
}
|
||||
} else {
|
||||
HILOG_DEBUG(LOG_CORE, "OnGetCommandResponse FAIL");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "OnGetCommandResponse OK %d", nrr.command_id());
|
||||
NotifyResult(nrr);
|
||||
return true;
|
||||
}
|
52
device/plugins/api/src/command_poller.h
Executable file
52
device/plugins/api/src/command_poller.h
Executable file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_POLLER_H
|
||||
#define COMMAND_POLLER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
class PluginManager;
|
||||
class CreateSessionCmd;
|
||||
class DestroySessionCmd;
|
||||
class StartSessionCmd;
|
||||
class StopSessionCmd;
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugin_service.ipc.h"
|
||||
|
||||
using PluginManagerPtr = STD_PTR(shared, PluginManager);
|
||||
|
||||
class CommandPoller final : public IPluginServiceClient {
|
||||
public:
|
||||
explicit CommandPoller(const PluginManagerPtr& p);
|
||||
~CommandPoller();
|
||||
|
||||
bool OnCreateSessionCmd(const CreateSessionCmd& cmd, SocketContext& context) const;
|
||||
bool OnDestroySessionCmd(const DestroySessionCmd& cmd) const;
|
||||
bool OnStartSessionCmd(const StartSessionCmd& cmd) const;
|
||||
bool OnStopSessionCmd(const StopSessionCmd& cmd) const;
|
||||
|
||||
uint32_t GetRequestId();
|
||||
|
||||
protected:
|
||||
bool OnGetCommandResponse(SocketContext& context, ::GetCommandResponse& response) override;
|
||||
|
||||
private:
|
||||
uint32_t requestIdAutoIncrease_;
|
||||
std::weak_ptr<PluginManager> pluginManager_;
|
||||
};
|
||||
|
||||
#endif // !COMMAND_POLLER_H
|
58
device/plugins/api/src/main.cpp
Executable file
58
device/plugins/api/src/main.cpp
Executable file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "command_poller.h"
|
||||
#include "logging.h"
|
||||
#include "plugin_manager.h"
|
||||
#include "plugin_service_types.pb.h"
|
||||
#include "plugin_watcher.h"
|
||||
#include "schedule_task_manager.h"
|
||||
#include "writer_adapter.h"
|
||||
|
||||
namespace {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
const char DEFAULT_PLUGIN_PATH[] = "./";
|
||||
#else
|
||||
const char DEFAULT_PLUGIN_PATH[] = "/data/local/tmp/";
|
||||
#endif
|
||||
|
||||
const int SLEEP_ONE_SECOND = 1000;
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::string pluginDir(DEFAULT_PLUGIN_PATH);
|
||||
if (argv[1] != nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "pluginDir = %s", argv[1]);
|
||||
pluginDir = argv[1];
|
||||
}
|
||||
|
||||
auto pluginManager = std::make_shared<PluginManager>();
|
||||
CHECK_NOTNULL(pluginManager, 1, "create PluginManager FAILED!");
|
||||
|
||||
auto commandPoller = std::make_shared<CommandPoller>(pluginManager);
|
||||
CHECK_NOTNULL(commandPoller, 1, "create CommandPoller FAILED!");
|
||||
pluginManager->SetCommandPoller(commandPoller);
|
||||
|
||||
PluginWatcher watcher(pluginManager);
|
||||
watcher.ScanPlugins(pluginDir);
|
||||
watcher.WatchPlugins(pluginDir);
|
||||
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_ONE_SECOND));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
358
device/plugins/api/src/plugin_manager.cpp
Normal file
358
device/plugins/api/src/plugin_manager.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "plugin_manager.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "command_poller.h"
|
||||
#include "logging.h"
|
||||
#include "plugin_service_types.pb.h"
|
||||
|
||||
PluginManager::~PluginManager() {}
|
||||
|
||||
void PluginManager::SetCommandPoller(const CommandPollerPtr& p)
|
||||
{
|
||||
this->commandPoller_ = p;
|
||||
}
|
||||
|
||||
bool PluginManager::AddPlugin(const std::string& pluginPath)
|
||||
{
|
||||
PluginModuleInfo info;
|
||||
|
||||
if (pluginIds_.find(pluginPath) != pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "already add");
|
||||
return false;
|
||||
}
|
||||
auto plugin = std::make_shared<PluginModule>(pluginPath);
|
||||
if (!plugin->Load()) {
|
||||
HILOG_DEBUG(LOG_CORE, "load failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!plugin->BindFunctions()) {
|
||||
HILOG_DEBUG(LOG_CORE, "BindFunctions failed %s", pluginPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!plugin->GetInfo(info)) {
|
||||
HILOG_DEBUG(LOG_CORE, "getinfo failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
HILOG_DEBUG(LOG_CORE, "add plugin name = %s", pluginPath.c_str());
|
||||
|
||||
if (!plugin->Unload()) {
|
||||
HILOG_DEBUG(LOG_CORE, "unload failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
RegisterPluginRequest request;
|
||||
request.set_request_id(commandPoller_->GetRequestId());
|
||||
request.set_path(pluginPath);
|
||||
request.set_sha256("");
|
||||
request.set_name(pluginPath);
|
||||
request.set_buffer_size_hint(0);
|
||||
RegisterPluginResponse response;
|
||||
|
||||
if (commandPoller_->RegisterPlugin(request, response)) {
|
||||
if (response.status() == 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "response.plugin_id() = %d", response.plugin_id());
|
||||
pluginIds_[pluginPath] = response.plugin_id();
|
||||
pluginModules_.insert(std::pair<uint32_t, std::shared_ptr<PluginModule>>(response.plugin_id(), plugin));
|
||||
HILOG_DEBUG(LOG_CORE, "RegisterPlugin OK");
|
||||
} else {
|
||||
HILOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 1");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
HILOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 2");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::RemovePlugin(const std::string& pluginPath)
|
||||
{
|
||||
auto it = pluginIds_.find(pluginPath);
|
||||
if (it == pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
uint32_t index = it->second;
|
||||
|
||||
UnregisterPluginRequest request;
|
||||
request.set_request_id(commandPoller_->GetRequestId());
|
||||
request.set_plugin_id(index);
|
||||
UnregisterPluginResponse response;
|
||||
if (commandPoller_->UnregisterPlugin(request, response)) {
|
||||
if (response.status() != 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 1");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
HILOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 2");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto itPluginModules = pluginModules_.find(index);
|
||||
if (it == pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
pluginModules_.erase(itPluginModules);
|
||||
pluginIds_.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::LoadPlugin(const std::string& pluginPath)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "size = %zu", pluginIds_.size());
|
||||
auto it = pluginIds_.find(pluginPath);
|
||||
if (it == pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
uint32_t index = it->second;
|
||||
|
||||
if (!pluginModules_[index]->Load()) {
|
||||
return false;
|
||||
}
|
||||
if (!pluginModules_[index]->BindFunctions()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::UnloadPlugin(const std::string& pluginPath)
|
||||
{
|
||||
auto it = pluginIds_.find(pluginPath);
|
||||
if (it == pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
return UnloadPlugin(it->second);
|
||||
}
|
||||
|
||||
bool PluginManager::UnloadPlugin(const uint32_t pluginId)
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s:UnloadPlugin ready!", __func__);
|
||||
if (pluginModules_.find(pluginId) == pluginModules_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
if (!pluginModules_[pluginId]->Unload()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& config)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "CreatePluginSession");
|
||||
|
||||
for (size_t idx = 0; idx < config.size(); ++idx) {
|
||||
HILOG_DEBUG(LOG_CORE, "config->name() = %s", config[idx].name().c_str());
|
||||
auto it = pluginIds_.find(config[idx].name());
|
||||
if (it == pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not find");
|
||||
return false;
|
||||
}
|
||||
|
||||
HILOG_DEBUG(LOG_CORE, "index = %d", it->second);
|
||||
pluginModules_[it->second]->SetConfigData(config[idx].config_data());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::DestroyPluginSession(const std::vector<uint32_t>& pluginIds)
|
||||
{
|
||||
for (uint32_t id : pluginIds) {
|
||||
auto it = pluginModules_.find(id);
|
||||
if (it == pluginModules_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not find");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::StartPluginSession(const std::vector<uint32_t>& pluginIds,
|
||||
const std::vector<ProfilerPluginConfig>& config)
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s: ready!", __func__);
|
||||
size_t idx = 0;
|
||||
|
||||
for (uint32_t id : pluginIds) {
|
||||
auto it = pluginModules_.find(id);
|
||||
if (it == pluginModules_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not find");
|
||||
return false;
|
||||
}
|
||||
auto configData = pluginModules_[id]->GetConfigData();
|
||||
if (!pluginModules_[id]->StartSession(
|
||||
reinterpret_cast<const uint8_t*>(configData.c_str()), configData.size())) {
|
||||
return false;
|
||||
}
|
||||
if (pluginModules_[id]->GetSampleMode() == PluginModule::POLLING) {
|
||||
if (idx > config.size()) {
|
||||
HILOG_WARN(LOG_CORE, "idx %d out of size %zu", idx, config.size());
|
||||
return false;
|
||||
}
|
||||
uint32_t sampleInterval = config[idx].sample_interval();
|
||||
std::string pluginName = config[idx].name();
|
||||
HILOG_DEBUG(LOG_CORE, "sampleInterval = %d", sampleInterval);
|
||||
HILOG_DEBUG(LOG_CORE, "name = %s", pluginName.c_str());
|
||||
if (!scheduleTaskManager_.ScheduleTask(pluginName, std::bind(&PluginManager::PullResult, this, id),
|
||||
ScheduleTaskManager::ms(sampleInterval))) {
|
||||
HILOG_DEBUG(LOG_CORE, "ScheduleTask failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::StopPluginSession(const std::vector<uint32_t>& pluginIds)
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s:stop session ready!", __func__);
|
||||
for (uint32_t id : pluginIds) {
|
||||
if (pluginModules_.find(id) == pluginModules_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not find");
|
||||
return false;
|
||||
}
|
||||
if (pluginModules_[id]->GetSampleMode() == PluginModule::POLLING) {
|
||||
for (auto it : pluginIds_) {
|
||||
if (it.second == id) {
|
||||
HILOG_DEBUG(LOG_CORE, "find plugin name = %s", it.first.c_str());
|
||||
if (!scheduleTaskManager_.UnscheduleTask(it.first)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pluginModules_[id]->StopSession()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::SubmitResult(const PluginResult& pluginResult)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "==================SubmitResult ===============");
|
||||
NotifyResultRequest request;
|
||||
if (commandPoller_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "SubmitResult:commandPoller_ is null");
|
||||
return false;
|
||||
}
|
||||
request.set_request_id(commandPoller_->GetRequestId());
|
||||
request.set_command_id(0);
|
||||
PluginResult* p = request.add_result();
|
||||
*p = pluginResult;
|
||||
NotifyResultResponse response;
|
||||
if (!commandPoller_->NotifyResult(request, response)) {
|
||||
HILOG_DEBUG(LOG_CORE, "SubmitResult FAIL 1");
|
||||
return false;
|
||||
}
|
||||
if (response.status() != 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "SubmitResult FAIL 2");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "SubmitResult OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::PullResult(uint32_t pluginId)
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s: ready!", __func__);
|
||||
uint32_t size = 0;
|
||||
std::string name;
|
||||
HILOG_DEBUG(LOG_CORE, "PullResult pluginId = %d", pluginId);
|
||||
auto it = pluginModules_.find(pluginId);
|
||||
if (it == pluginModules_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not find");
|
||||
return false;
|
||||
}
|
||||
pluginModules_[pluginId]->GetBufferSizeHint(size);
|
||||
pluginModules_[pluginId]->GetPluginName(name);
|
||||
std::unique_ptr<uint8_t[]> buffer {new (std::nothrow) uint8_t[size]};
|
||||
if (buffer == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "buffer new failed!");
|
||||
} else {
|
||||
HILOG_DEBUG(LOG_CORE, "buffer new success!");
|
||||
}
|
||||
|
||||
int length = it->second->ReportResult(buffer.get(), size);
|
||||
if (length < 0) {
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "PullResult length = %d", length);
|
||||
HILOG_DEBUG(LOG_CORE, "PullResult name = %s", name.c_str());
|
||||
|
||||
ProfilerPluginData pluginData;
|
||||
pluginData.set_name(name);
|
||||
pluginData.set_status(0);
|
||||
pluginData.set_data(buffer.get(), length);
|
||||
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
pluginData.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME);
|
||||
pluginData.set_tv_sec(ts.tv_sec);
|
||||
pluginData.set_tv_nsec(ts.tv_nsec);
|
||||
|
||||
auto writer = pluginModules_[pluginId]->GetWriter();
|
||||
CHECK_NOTNULL(writer, false, "PullResult GetWriter nullptr");
|
||||
|
||||
std::static_pointer_cast<BufferWriter>(writer)->WriteProtobuf(pluginData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int fd)
|
||||
{
|
||||
auto it = pluginIds_.find(pluginName);
|
||||
if (it == pluginIds_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
uint32_t index = it->second;
|
||||
|
||||
if (bufferSize > 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "%s Use ShareMemory %d", pluginName.c_str(), bufferSize);
|
||||
pluginModules_[index]->RegisterWriter(
|
||||
std::make_shared<BufferWriter>(pluginName, bufferSize, fd, commandPoller_, index));
|
||||
} else {
|
||||
HILOG_ERROR(LOG_CORE, "no shared memory buffer allocated!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::ResetWriter(uint32_t pluginId)
|
||||
{
|
||||
if (pluginModules_.find(pluginId) == pluginModules_.end()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not exist");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "ResetWriter %u", pluginId);
|
||||
pluginModules_[pluginId]->RegisterWriter(nullptr);
|
||||
return true;
|
||||
}
|
64
device/plugins/api/src/plugin_manager.h
Normal file
64
device/plugins/api/src/plugin_manager.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_MANAGER_H
|
||||
#define PLUGIN_MANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "plugin_module.h"
|
||||
#include "schedule_task_manager.h"
|
||||
|
||||
class ProfilerPluginConfig;
|
||||
class PluginResult;
|
||||
class CommandPoller;
|
||||
|
||||
class PluginManager {
|
||||
public:
|
||||
virtual ~PluginManager();
|
||||
bool AddPlugin(const std::string& pluginPath);
|
||||
bool RemovePlugin(const std::string& pluginPath);
|
||||
|
||||
bool LoadPlugin(const std::string& pluginPath);
|
||||
bool UnloadPlugin(const std::string& pluginPath);
|
||||
bool UnloadPlugin(const uint32_t pluginId);
|
||||
|
||||
// CommandPoller will call the following four interfaces after receiving the command
|
||||
bool CreatePluginSession(const std::vector<ProfilerPluginConfig>& config);
|
||||
bool DestroyPluginSession(const std::vector<uint32_t>& pluginIds);
|
||||
bool StartPluginSession(const std::vector<uint32_t>& pluginIds, const std::vector<ProfilerPluginConfig>& config);
|
||||
bool StopPluginSession(const std::vector<uint32_t>& pluginIds);
|
||||
|
||||
// call the 'PluginModule::ReportResult' and 'PluginManager::SubmitResult' according to 'pluginId'
|
||||
// creat PluginResult for current plug-in inside
|
||||
bool PullResult(uint32_t pluginId);
|
||||
|
||||
// for test
|
||||
virtual bool SubmitResult(const PluginResult& pluginResult);
|
||||
bool CreateWriter(std::string pluginName, uint32_t bufferSize, int fd);
|
||||
bool ResetWriter(uint32_t pluginId);
|
||||
void SetCommandPoller(const CommandPollerPtr& p);
|
||||
|
||||
private:
|
||||
std::map<uint32_t, std::shared_ptr<PluginModule>> pluginModules_;
|
||||
std::map<std::string, uint32_t> pluginIds_; // pluginName maps to pluginId
|
||||
CommandPollerPtr commandPoller_;
|
||||
ScheduleTaskManager scheduleTaskManager_;
|
||||
};
|
||||
|
||||
#endif // PLUGIN_MANAGER_H
|
241
device/plugins/api/src/plugin_module.cpp
Normal file
241
device/plugins/api/src/plugin_module.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "plugin_module.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugin_module_api.h"
|
||||
|
||||
PluginModule::PluginModule(const std::string& path) : handle_(nullptr), path_(path), structPtr_(nullptr) {}
|
||||
|
||||
PluginModule::~PluginModule() {}
|
||||
|
||||
std::string PluginModule::ComputeSha256()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool PluginModule::Load()
|
||||
{
|
||||
char realPath[PATH_MAX + 1] = {0};
|
||||
if (handle_ != nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "already open");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (realpath(path_.c_str(), realPath) == nullptr) {
|
||||
HILOG_ERROR(LOG_CORE, "so filename invalid, errno=%d", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string rpath = realPath; // for SC warning
|
||||
handle_ = dlopen(rpath.c_str(), RTLD_NOW);
|
||||
if (handle_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "dlopen err:%s.", dlerror());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginModule::Unload()
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s:unload ready!", __func__);
|
||||
if (handle_ != nullptr) {
|
||||
HILOG_INFO(LOG_CORE, "Unload plugin");
|
||||
int ret = dlclose(handle_);
|
||||
HILOG_INFO(LOG_CORE, "Unload plugin ret = %d", ret);
|
||||
handle_ = nullptr;
|
||||
structPtr_ = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginModule::GetInfo(PluginModuleInfo& info)
|
||||
{
|
||||
if (handle_ != nullptr) {
|
||||
if (structPtr_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
info.bufferSizeHint = structPtr_->resultBufferSizeHint;
|
||||
info.name.assign(structPtr_->name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PluginModule::SampleMode PluginModule::GetSampleMode() const
|
||||
{
|
||||
if (structPtr_ && structPtr_->callbacks) {
|
||||
if (structPtr_->callbacks->onPluginReportResult != nullptr) {
|
||||
return POLLING;
|
||||
} else if (structPtr_->callbacks->onRegisterWriterStruct != nullptr) {
|
||||
return STREAMING;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
void PluginModule::SetConfigData(const std::string& data)
|
||||
{
|
||||
configData_ = data;
|
||||
}
|
||||
|
||||
std::string PluginModule::GetConfigData() const
|
||||
{
|
||||
return configData_;
|
||||
}
|
||||
|
||||
bool PluginModule::GetPluginName(std::string& pluginName)
|
||||
{
|
||||
if (handle_ != nullptr) {
|
||||
if (structPtr_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
pluginName.assign(structPtr_->name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginModule::GetBufferSizeHint(uint32_t& bufferSizeHint)
|
||||
{
|
||||
if (handle_ != nullptr) {
|
||||
if (structPtr_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
bufferSizeHint = structPtr_->resultBufferSizeHint;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginModule::IsLoaded()
|
||||
{
|
||||
return (handle_ != nullptr);
|
||||
}
|
||||
bool PluginModule::BindFunctions()
|
||||
{
|
||||
if (handle_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not load");
|
||||
return false;
|
||||
}
|
||||
if (structPtr_ == nullptr) {
|
||||
structPtr_ = (PluginModuleStruct*)dlsym(handle_, "g_pluginModule");
|
||||
if (structPtr_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "structPtr_ == nullptr");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (structPtr_->callbacks == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "structPtr_->callbacks == nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((structPtr_->callbacks->onPluginSessionStart == nullptr) ||
|
||||
(structPtr_->callbacks->onPluginSessionStop == nullptr)) {
|
||||
HILOG_DEBUG(LOG_CORE, "onPluginSessionStart == nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginModule::StartSession(const uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
HILOG_DEBUG(LOG_CORE, "StartSession");
|
||||
if (handle_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not load");
|
||||
return false;
|
||||
}
|
||||
HILOG_DEBUG(LOG_CORE, "size = %u, ", size);
|
||||
|
||||
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
|
||||
if (structPtr_->callbacks->onPluginSessionStart) {
|
||||
return (structPtr_->callbacks->onPluginSessionStart(buffer, size) == 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginModule::StopSession()
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s:stop Session ready!", __func__);
|
||||
if (handle_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not load");
|
||||
return false;
|
||||
}
|
||||
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
|
||||
if (structPtr_->callbacks->onPluginSessionStop != nullptr) {
|
||||
return (structPtr_->callbacks->onPluginSessionStop() == 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t PluginModule::ReportResult(uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "%s: ready!", __func__);
|
||||
HILOG_DEBUG(LOG_CORE, "ReportResult");
|
||||
if (handle_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin not open");
|
||||
return -1;
|
||||
}
|
||||
if (first_) {
|
||||
lastTime_ = std::chrono::steady_clock::now();
|
||||
first_ = false;
|
||||
} else {
|
||||
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<int, std::milli> interval =
|
||||
std::chrono::duration_cast<std::chrono::duration<int, std::milli>>(t1 - lastTime_);
|
||||
HILOG_DEBUG(LOG_CORE, "the id equals %u interval is %d milli seconds", size, interval.count());
|
||||
lastTime_ = t1;
|
||||
}
|
||||
|
||||
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
|
||||
if (structPtr_->callbacks->onPluginReportResult != nullptr) {
|
||||
HILOG_INFO(LOG_CORE, "%s: call plugin ready!", __func__);
|
||||
return structPtr_->callbacks->onPluginReportResult(buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool PluginModule::RegisterWriter(const BufferWriterPtr writer)
|
||||
{
|
||||
writerAdapter_ = std::make_shared<WriterAdapter>();
|
||||
writerAdapter_->SetWriter(writer);
|
||||
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
|
||||
if (structPtr_->callbacks->onRegisterWriterStruct != nullptr) {
|
||||
return structPtr_->callbacks->onRegisterWriterStruct(writerAdapter_->GetStruct());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
WriterPtr PluginModule::GetWriter()
|
||||
{
|
||||
if (writerAdapter_ == nullptr) {
|
||||
HILOG_DEBUG(LOG_CORE, "PluginModule 111111, nullptr");
|
||||
return nullptr;
|
||||
}
|
||||
return writerAdapter_->GetWriter();
|
||||
}
|
81
device/plugins/api/src/plugin_module.h
Normal file
81
device/plugins/api/src/plugin_module.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_MODULE_H
|
||||
#define PLUGIN_MODULE_H
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "buffer_writer.h"
|
||||
#include "writer_adapter.h"
|
||||
|
||||
struct PluginModuleInfo {
|
||||
std::string name;
|
||||
uint32_t bufferSizeHint = 0;
|
||||
};
|
||||
|
||||
struct PluginModuleStruct;
|
||||
struct WriterStruct;
|
||||
|
||||
using BufferWriterPtr = STD_PTR(shared, BufferWriter);
|
||||
|
||||
class PluginModule {
|
||||
public:
|
||||
enum SampleMode {
|
||||
UNKNOWN,
|
||||
POLLING,
|
||||
STREAMING,
|
||||
};
|
||||
explicit PluginModule(const std::string& path = "");
|
||||
~PluginModule();
|
||||
std::string ComputeSha256();
|
||||
|
||||
bool Load();
|
||||
bool Unload();
|
||||
|
||||
SampleMode GetSampleMode() const;
|
||||
bool GetInfo(PluginModuleInfo& info);
|
||||
bool GetPluginName(std::string& pluginName);
|
||||
bool GetBufferSizeHint(uint32_t& bufferSizeHint);
|
||||
|
||||
bool IsLoaded();
|
||||
bool BindFunctions();
|
||||
|
||||
bool StartSession(const uint8_t* buffer, uint32_t size);
|
||||
bool StopSession();
|
||||
int32_t ReportResult(uint8_t* buffer, uint32_t size);
|
||||
|
||||
bool RegisterWriter(const BufferWriterPtr writer);
|
||||
WriterPtr GetWriter();
|
||||
|
||||
void SetConfigData(const std::string& data);
|
||||
std::string GetConfigData() const;
|
||||
|
||||
private:
|
||||
void* handle_;
|
||||
std::string path_;
|
||||
std::string pluginName_;
|
||||
std::string configData_;
|
||||
PluginModuleStruct* structPtr_;
|
||||
|
||||
std::shared_ptr<WriterAdapter> writerAdapter_;
|
||||
|
||||
std::chrono::steady_clock::time_point lastTime_;
|
||||
bool first_ = true;
|
||||
};
|
||||
|
||||
#endif // !PLUGIN_MODULE_H
|
184
device/plugins/api/src/plugin_watcher.cpp
Executable file
184
device/plugins/api/src/plugin_watcher.cpp
Executable file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "plugin_watcher.h"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <dirent.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugin_manager.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t MAX_BUF_SIZE = 1024;
|
||||
} // namespace
|
||||
|
||||
PluginWatcher::PluginWatcher(const PluginManagerPtr& pluginManager)
|
||||
: inotifyFd_(-1), pluginManager_(pluginManager), runMonitor_(true)
|
||||
{
|
||||
inotifyFd_ = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
|
||||
if (inotifyFd_ < 0) {
|
||||
HILOG_INFO(LOG_CORE, "%s inotify_init1 failed! inotifyFd_ : %d", __FUNCTION__, inotifyFd_);
|
||||
} else {
|
||||
monitorThread_ = std::thread(&PluginWatcher::Monitor, this);
|
||||
}
|
||||
}
|
||||
|
||||
PluginWatcher::~PluginWatcher()
|
||||
{
|
||||
runMonitor_ = false;
|
||||
for (auto it = wdToDir_.begin(); it != wdToDir_.end(); ++it) {
|
||||
inotify_rm_watch(inotifyFd_, it->first);
|
||||
}
|
||||
|
||||
if (inotifyFd_ != -1) {
|
||||
close(inotifyFd_);
|
||||
}
|
||||
monitorThread_.join();
|
||||
}
|
||||
|
||||
void PluginWatcher::ScanPlugins(const std::string& pluginDir)
|
||||
{
|
||||
DIR* dir = nullptr;
|
||||
struct dirent* entry = nullptr;
|
||||
char fullpath[PATH_MAX + 1] = {0};
|
||||
realpath(pluginDir.c_str(), fullpath);
|
||||
HILOG_INFO(LOG_CORE, "scan plugin from directory %s", fullpath);
|
||||
dir = opendir(fullpath);
|
||||
if (dir == nullptr) {
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
entry = readdir(dir);
|
||||
if (!entry) {
|
||||
HILOG_INFO(LOG_CORE, "%s readdir finish!", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
std::string fileName = entry->d_name;
|
||||
if (entry->d_type & DT_REG) {
|
||||
size_t pos = fileName.rfind(".so");
|
||||
if (pos != std::string::npos && (pos == fileName.length() - strlen(".so"))) {
|
||||
OnPluginAdded(std::string(fullpath) + '/' + fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
void PluginWatcher::WatchPlugins(const std::string& pluginDir)
|
||||
{
|
||||
char fullpath[PATH_MAX + 1] = {0};
|
||||
realpath(pluginDir.c_str(), fullpath);
|
||||
|
||||
int wd = inotify_add_watch(inotifyFd_, fullpath, IN_ALL_EVENTS);
|
||||
if (wd < 0) {
|
||||
HILOG_INFO(LOG_CORE, "inotify_add_watch add directory %s failed", pluginDir.c_str());
|
||||
return;
|
||||
}
|
||||
HILOG_INFO(LOG_CORE, "inotify_add_watch add directory %s success", fullpath);
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
wdToDir_.insert(std::pair<int, std::string>(wd, std::string(fullpath)));
|
||||
}
|
||||
|
||||
void PluginWatcher::Monitor()
|
||||
{
|
||||
const struct inotify_event* event = nullptr;
|
||||
char buffer[MAX_BUF_SIZE] = {'\0'};
|
||||
struct timeval time;
|
||||
char* ptr = nullptr;
|
||||
int ret = 0;
|
||||
|
||||
while (runMonitor_) {
|
||||
fd_set rFds;
|
||||
FD_ZERO(&rFds);
|
||||
FD_SET(inotifyFd_, &rFds);
|
||||
time.tv_sec = 1;
|
||||
time.tv_usec = 0;
|
||||
ret = select(inotifyFd_ + 1, &rFds, nullptr, nullptr, &time);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
} else if (!ret) {
|
||||
continue;
|
||||
} else if (FD_ISSET(inotifyFd_, &rFds)) {
|
||||
ssize_t readLength = read(inotifyFd_, buffer, MAX_BUF_SIZE);
|
||||
if (readLength == -1) {
|
||||
continue;
|
||||
}
|
||||
for (ptr = buffer; ptr < buffer + readLength; ptr += sizeof(struct inotify_event) + event->len) {
|
||||
event = reinterpret_cast<const struct inotify_event*>(ptr);
|
||||
std::unique_lock<std::mutex> guard(mtx_, std::adopt_lock);
|
||||
const std::string& pluginDir = wdToDir_[event->wd];
|
||||
guard.unlock();
|
||||
if (event->mask & IN_ISDIR) {
|
||||
continue;
|
||||
}
|
||||
std::string fileName = event->name;
|
||||
size_t pos = fileName.rfind(".so");
|
||||
if (pos == std::string::npos || (pos != fileName.length() - strlen(".so"))) {
|
||||
continue;
|
||||
}
|
||||
switch (event->mask) {
|
||||
case IN_CLOSE_WRITE:
|
||||
case IN_MOVED_TO:
|
||||
OnPluginAdded(pluginDir + '/' + fileName);
|
||||
break;
|
||||
case IN_DELETE:
|
||||
case IN_MOVED_FROM:
|
||||
OnPluginRemoved(pluginDir + '/' + fileName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (memset_s(buffer, MAX_BUF_SIZE, 0, MAX_BUF_SIZE) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "memset_s error!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PluginWatcher::OnPluginAdded(const std::string& pluginPath)
|
||||
{
|
||||
auto pluginManager = pluginManager_.lock();
|
||||
if (pluginManager != nullptr) {
|
||||
if (pluginManager->AddPlugin(pluginPath)) {
|
||||
HILOG_INFO(LOG_CORE, "plugin %s add success", pluginPath.c_str());
|
||||
} else {
|
||||
HILOG_INFO(LOG_CORE, "pluginPath %s add failed", pluginPath.c_str());
|
||||
}
|
||||
} else {
|
||||
HILOG_INFO(LOG_CORE, "%s weak_ptr pluginManager lock failed!", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginWatcher::OnPluginRemoved(const std::string& pluginPath)
|
||||
{
|
||||
auto pluginManager = pluginManager_.lock();
|
||||
if (pluginManager != nullptr) {
|
||||
if (pluginManager->RemovePlugin(pluginPath)) {
|
||||
HILOG_INFO(LOG_CORE, "pluginPath %s remove success", pluginPath.c_str());
|
||||
} else {
|
||||
HILOG_INFO(LOG_CORE, "pluginPath %s remove failed", pluginPath.c_str());
|
||||
}
|
||||
} else {
|
||||
HILOG_INFO(LOG_CORE, "%s weak_ptr pluginManager lock failed!", __FUNCTION__);
|
||||
}
|
||||
}
|
53
device/plugins/api/src/plugin_watcher.h
Executable file
53
device/plugins/api/src/plugin_watcher.h
Executable file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_WATCHER_H
|
||||
#define PLUGIN_WATCHER_H
|
||||
|
||||
#include <logging.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
class PluginManager;
|
||||
|
||||
using PluginManagerPtr = STD_PTR(shared, PluginManager);
|
||||
|
||||
class PluginWatcher {
|
||||
public:
|
||||
explicit PluginWatcher(const PluginManagerPtr& pluginManager);
|
||||
~PluginWatcher();
|
||||
|
||||
void ScanPlugins(const std::string& pluginDir);
|
||||
|
||||
void WatchPlugins(const std::string& pluginDir);
|
||||
|
||||
private:
|
||||
int inotifyFd_;
|
||||
std::weak_ptr<PluginManager> pluginManager_;
|
||||
std::map<int, std::string> wdToDir_;
|
||||
std::thread monitorThread_;
|
||||
std::mutex mtx_;
|
||||
bool runMonitor_;
|
||||
|
||||
virtual void OnPluginAdded(const std::string& pluginPath);
|
||||
virtual void OnPluginRemoved(const std::string& pluginPath);
|
||||
void MonitorEventName(uint32_t mask, const std::string& fileName, const std::string& pluginDir);
|
||||
void Monitor();
|
||||
};
|
||||
|
||||
#endif // !PLUGIN_WATCHER_H
|
57
device/plugins/api/src/writer_adapter.cpp
Executable file
57
device/plugins/api/src/writer_adapter.cpp
Executable file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "writer_adapter.h"
|
||||
|
||||
WriterAdapter::WriterAdapter()
|
||||
{
|
||||
writerStruct_.write = &WriterAdapter::WriteFunc;
|
||||
writerStruct_.flush = &WriterAdapter::FlushFunc;
|
||||
}
|
||||
|
||||
WriterAdapter::~WriterAdapter() {}
|
||||
|
||||
void WriterAdapter::SetWriter(const WriterPtr& writer)
|
||||
{
|
||||
writer_ = writer;
|
||||
}
|
||||
|
||||
WriterPtr WriterAdapter::GetWriter()
|
||||
{
|
||||
return writer_;
|
||||
}
|
||||
|
||||
const WriterStruct* WriterAdapter::GetStruct()
|
||||
{
|
||||
return &writerStruct_;
|
||||
}
|
||||
|
||||
long WriterAdapter::WriteFunc(WriterStruct* writer, const void* data, size_t size)
|
||||
{
|
||||
WriterAdapter* writerAdaptor = reinterpret_cast<WriterAdapter*>(writer);
|
||||
if (writerAdaptor && writerAdaptor->writer_) {
|
||||
return writerAdaptor->writer_->Write(data, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WriterAdapter::FlushFunc(WriterStruct* writer)
|
||||
{
|
||||
WriterAdapter* writerAdaptor = reinterpret_cast<WriterAdapter*>(writer);
|
||||
if (writerAdaptor && writerAdaptor->writer_) {
|
||||
return writerAdaptor->writer_->Flush();
|
||||
}
|
||||
return false;
|
||||
}
|
42
device/plugins/api/src/writer_adapter.h
Executable file
42
device/plugins/api/src/writer_adapter.h
Executable file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WRITER_ADAPTER_H
|
||||
#define WRITER_ADAPTER_H
|
||||
|
||||
#include <memory>
|
||||
#include "logging.h"
|
||||
#include "plugin_module_api.h"
|
||||
#include "writer.h"
|
||||
|
||||
using WriterPtr = STD_PTR(shared, Writer);
|
||||
class WriterAdapter {
|
||||
public:
|
||||
WriterAdapter();
|
||||
~WriterAdapter();
|
||||
const WriterStruct* GetStruct();
|
||||
void SetWriter(const WriterPtr& writer);
|
||||
WriterPtr GetWriter();
|
||||
|
||||
private:
|
||||
static long WriteFunc(WriterStruct* writer, const void* data, size_t size);
|
||||
static bool FlushFunc(WriterStruct* writer);
|
||||
|
||||
private:
|
||||
WriterStruct writerStruct_;
|
||||
WriterPtr writer_;
|
||||
};
|
||||
|
||||
#endif // !WRITER_ADAPTER_H
|
64
device/plugins/api/test/BUILD.gn
Executable file
64
device/plugins/api/test/BUILD.gn
Executable file
@ -0,0 +1,64 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/test.gni")
|
||||
import("../../../base/config.gni")
|
||||
|
||||
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
|
||||
config("module_private_config") {
|
||||
visibility = [":*"]
|
||||
}
|
||||
|
||||
config("cflags_config") {
|
||||
cflags = [
|
||||
"-Wno-sign-compare",
|
||||
"-pthread",
|
||||
"-Dprivate=public", #allow test code access private members
|
||||
"-Dprotected=public", #allow test code access private members
|
||||
]
|
||||
}
|
||||
|
||||
ohos_unittest("hiprofiler_plugins_ut") {
|
||||
module_out_path = module_output_path
|
||||
deps = [
|
||||
"../:plugins_sources",
|
||||
"${OHOS_PROFILER_DIR}/device/services/plugin_service:hiprofiler_plugin_service",
|
||||
"${OHOS_PROFILER_DIR}/device/services/profiler_service:profiler_service",
|
||||
"//third_party/googletest:gmock",
|
||||
"//third_party/googletest:gtest",
|
||||
]
|
||||
include_dirs = [
|
||||
"//third_party/googletest/googletest/include/gtest",
|
||||
]
|
||||
sources = [
|
||||
"unittest/writer_adapter_test.cpp",
|
||||
"unittest/plugin_manager_test.cpp",
|
||||
"unittest/plugin_watcher_test.cpp",
|
||||
"unittest/services_ipc_test.cpp",
|
||||
"unittest/services_profiler_service_test.cpp",
|
||||
"unittest/services_shared_memory_test.cpp",
|
||||
"unittest/services_plugin_service_test.cpp",
|
||||
]
|
||||
configs = [ ":cflags_config" ]
|
||||
external_deps = [
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
]
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [
|
||||
":hiprofiler_plugins_ut",
|
||||
]
|
||||
}
|
148
device/plugins/api/test/unittest/plugin_manager_test.cpp
Normal file
148
device/plugins/api/test/unittest/plugin_manager_test.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <grpcpp/health_check_service_interface.h>
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
#include <thread>
|
||||
|
||||
#include "command_poller.h"
|
||||
#include "grpc/impl/codegen/log.h"
|
||||
#include "logging.h"
|
||||
#include "plugin_manager.h"
|
||||
#include "plugin_service.h"
|
||||
#include "plugin_service.ipc.h"
|
||||
#include "profiler_service.h"
|
||||
#include "socket_context.h"
|
||||
|
||||
using google::protobuf::Message;
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
const static std::string SUCCESS_PLUGIN_NAME = "libmemdataplugin.z.so";
|
||||
std::string g_testPluginDir("/data/local/tmp/");
|
||||
|
||||
class PluginManagerTest : public ::testing::Test {
|
||||
protected:
|
||||
static constexpr auto TEMP_DELAY = std::chrono::milliseconds(20);
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
char pluginDir[PATH_MAX + 1] = {0};
|
||||
if (readlink("/proc/self/exe", pluginDir, PATH_MAX) > 0) {
|
||||
char* pos = strrchr(pluginDir, '/');
|
||||
if (pos != nullptr) {
|
||||
*(pos++) = '\0';
|
||||
printf("-----> pluginDir = %s\n", pluginDir);
|
||||
g_testPluginDir = pluginDir;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("======> pluginDir = %s\n", g_testPluginDir.c_str());
|
||||
|
||||
std::this_thread::sleep_for(TEMP_DELAY);
|
||||
printf("SetUpTestCase success\n");
|
||||
}
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Plug-in normal loading and removal process test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(PluginManagerTest, SuccessPlugin, TestSize.Level1)
|
||||
{
|
||||
auto pluginManage = std::make_shared<PluginManager>();
|
||||
auto commandPoller = std::make_shared<CommandPoller>(pluginManage);
|
||||
pluginManage->SetCommandPoller(commandPoller);
|
||||
|
||||
const uint8_t configData[] = {0x30, 0x01, 0x38, 0x01, 0x42, 0x01, 0x01};
|
||||
ProfilerPluginConfig config;
|
||||
const std::vector<uint32_t> pluginIdsVector = {1};
|
||||
config.set_name(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME);
|
||||
config.set_config_data((const void*)configData, 7);
|
||||
config.set_sample_interval(1000);
|
||||
|
||||
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->UnloadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->RemovePlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->RemovePlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
EXPECT_FALSE(pluginManage->UnloadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
|
||||
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
|
||||
|
||||
std::vector<ProfilerPluginConfig> configVec;
|
||||
configVec.push_back(config);
|
||||
EXPECT_FALSE(pluginManage->CreatePluginSession(configVec));
|
||||
|
||||
EXPECT_FALSE(pluginManage->StartPluginSession(pluginIdsVector, configVec));
|
||||
std::this_thread::sleep_for(TEMP_DELAY);
|
||||
|
||||
EXPECT_FALSE(pluginManage->StopPluginSession(pluginIdsVector));
|
||||
|
||||
EXPECT_FALSE(pluginManage->DestroyPluginSession(pluginIdsVector));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: get sample Mode.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(PluginManagerTest, GetSampleMode, TestSize.Level1)
|
||||
{
|
||||
PluginModule pluginModule;
|
||||
pluginModule.GetSampleMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Plug-in data acquisition process test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(PluginManagerTest, PluginManager, TestSize.Level1)
|
||||
{
|
||||
PluginManager pluginManager;
|
||||
PluginModuleInfo info;
|
||||
pluginManager.UnloadPlugin(0);
|
||||
PluginResult pluginResult;
|
||||
pluginManager.SubmitResult(pluginResult);
|
||||
pluginManager.PullResult(0);
|
||||
pluginManager.CreateWriter("", 0, -1);
|
||||
pluginManager.ResetWriter(-1);
|
||||
|
||||
PluginModule pluginModule;
|
||||
pluginModule.ComputeSha256();
|
||||
pluginModule.Unload();
|
||||
pluginModule.GetInfo(info);
|
||||
std::string str("memory-plugin");
|
||||
pluginModule.GetPluginName(str);
|
||||
uint32_t num = 0;
|
||||
pluginModule.GetBufferSizeHint(num);
|
||||
pluginModule.IsLoaded();
|
||||
|
||||
BufferWriter bufferWriter("", 0, -1, nullptr, 0);
|
||||
bufferWriter.Write(nullptr, 0);
|
||||
bufferWriter.Flush();
|
||||
}
|
||||
} // namespace
|
184
device/plugins/api/test/unittest/plugin_watcher_test.cpp
Executable file
184
device/plugins/api/test/unittest/plugin_watcher_test.cpp
Executable file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
#include "plugin_manager.h"
|
||||
#include "plugin_watcher.h"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
static std::vector<std::string> g_cmpFileList;
|
||||
static std::vector<std::string> g_createFileList = {
|
||||
"lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so", "test1.txt"
|
||||
};
|
||||
std::vector<int> g_createFdList;
|
||||
|
||||
static std::vector<std::string> g_addFileList = {
|
||||
"libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so", "test2.txt"
|
||||
};
|
||||
|
||||
static std::vector<std::string> g_expectFileList = {
|
||||
"libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so",
|
||||
"lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so"
|
||||
};
|
||||
|
||||
static int g_defaultFileMode = 0777;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
const static std::string DEFAULT_TEST_PATH = "./";
|
||||
#else
|
||||
const static std::string DEFAULT_TEST_PATH = "/data/local/tmp/";
|
||||
#endif
|
||||
|
||||
class PluginWatchTest : public ::testing::Test {
|
||||
protected:
|
||||
static constexpr int TEMP_DELAY = 10 * 1000;
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
|
||||
void SetUp() override {}
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
class MockPluginWatcher : public PluginWatcher {
|
||||
public:
|
||||
MockPluginWatcher(const PluginManagerPtr& pluginManager) : PluginWatcher(pluginManager) {}
|
||||
~MockPluginWatcher() = default;
|
||||
MOCK_METHOD1(OnPluginAdded, void(const std::string&));
|
||||
MOCK_METHOD1(OnPluginRemoved, void(const std::string&));
|
||||
};
|
||||
|
||||
static void OnPluginAddedStub(const std::string& path)
|
||||
{
|
||||
g_cmpFileList.push_back(path);
|
||||
sort(g_cmpFileList.begin(), g_cmpFileList.end());
|
||||
return;
|
||||
}
|
||||
|
||||
static void OnPluginRemovedStub(const std::string& path)
|
||||
{
|
||||
for (auto iter = g_cmpFileList.cbegin(); iter != g_cmpFileList.cend(); iter++) {
|
||||
if (*iter == path) {
|
||||
g_cmpFileList.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void CreateFile()
|
||||
{
|
||||
for (auto it : g_createFileList) {
|
||||
int fd = creat(it.c_str(), g_defaultFileMode);
|
||||
g_createFdList.push_back(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddFile()
|
||||
{
|
||||
for (auto it : g_addFileList) {
|
||||
int fd = creat(it.c_str(), g_defaultFileMode);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
write(fd, "testcase", 1);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void DeleteFile()
|
||||
{
|
||||
for (auto it : g_createFileList) {
|
||||
for (auto fd : g_createFdList) {
|
||||
close(fd);
|
||||
}
|
||||
remove(it.c_str());
|
||||
}
|
||||
for (auto it : g_addFileList) {
|
||||
remove(it.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static bool CheckFileList()
|
||||
{
|
||||
sort(g_expectFileList.begin(), g_expectFileList.end());
|
||||
if (g_expectFileList.size() != g_cmpFileList.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g_expectFileList.size(); i++) {
|
||||
char fullpath[PATH_MAX + 1] = {0};
|
||||
realpath(g_expectFileList.at(i).c_str(), fullpath);
|
||||
if (g_cmpFileList.at(i) != fullpath) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Monitor the plugin loading in the test directory.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(PluginWatchTest, SingleWatchDirTest, TestSize.Level1)
|
||||
{
|
||||
auto pluginManage = std::make_shared<PluginManager>();
|
||||
MockPluginWatcher watcher(pluginManage);
|
||||
|
||||
EXPECT_CALL(watcher, OnPluginAdded(testing::_)).WillRepeatedly(testing::Invoke(OnPluginAddedStub));
|
||||
EXPECT_CALL(watcher, OnPluginRemoved(testing::_)).WillRepeatedly(testing::Invoke(OnPluginRemovedStub));
|
||||
|
||||
g_createFdList.clear();
|
||||
CreateFile();
|
||||
watcher.ScanPlugins(DEFAULT_TEST_PATH);
|
||||
watcher.WatchPlugins(DEFAULT_TEST_PATH);
|
||||
usleep(TEMP_DELAY);
|
||||
AddFile();
|
||||
usleep(TEMP_DELAY);
|
||||
EXPECT_EQ(CheckFileList(), false);
|
||||
DeleteFile();
|
||||
usleep(TEMP_DELAY);
|
||||
EXPECT_EQ(g_cmpFileList.empty(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Plug-in process exception test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(PluginWatchTest, OnPluginAdded, TestSize.Level1)
|
||||
{
|
||||
const auto pluginManage = std::make_shared<PluginManager>();
|
||||
PluginWatcher pluginWatcher(pluginManage);
|
||||
pluginWatcher.OnPluginAdded("");
|
||||
pluginWatcher.OnPluginRemoved("");
|
||||
}
|
||||
} // namespace
|
118
device/plugins/api/test/unittest/services_ipc_test.cpp
Normal file
118
device/plugins/api/test/unittest/services_ipc_test.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
#include <thread>
|
||||
|
||||
#include "client_map.h"
|
||||
#include "plugin_service.ipc.h"
|
||||
#include "service_entry.h"
|
||||
#include "socket_context.h"
|
||||
#include "unix_socket_client.h"
|
||||
#include "unix_socket_server.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
class ServicesIpcTest : public ::testing::Test {
|
||||
protected:
|
||||
static constexpr auto TEMP_DELAY = std::chrono::milliseconds(10);
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: ipc
|
||||
* @tc.desc: Socket send/recv interface.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesIpcTest, ProtocolProc, TestSize.Level1)
|
||||
{
|
||||
ServiceBase serviceBase;
|
||||
SocketContext socketContext;
|
||||
ASSERT_FALSE(serviceBase.ProtocolProc(socketContext, 0, nullptr, 0));
|
||||
ASSERT_TRUE(!socketContext.SendRaw(-1, nullptr, 0, 0));
|
||||
ASSERT_TRUE(!socketContext.SendFileDescriptor(-1));
|
||||
ASSERT_EQ(socketContext.ReceiveFileDiscriptor(), -1);
|
||||
ASSERT_EQ(socketContext.RawProtocolProc(-1, nullptr, -1), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: ipc
|
||||
* @tc.desc: Client link.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesIpcTest, ClientSocket, TestSize.Level1)
|
||||
{
|
||||
ServiceEntry serviceEntry;
|
||||
ClientMap::GetInstance().PutClientSocket(0, serviceEntry);
|
||||
ASSERT_EQ(ClientMap::GetInstance().AutoRelease(), 1);
|
||||
|
||||
ClientConnection* clientConnection = new ClientConnection(0, serviceEntry);
|
||||
ASSERT_EQ(clientConnection->RawProtocolProc(-1, nullptr, 0), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Abnormal client link.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesIpcTest, unixSocketClient, TestSize.Level1)
|
||||
{
|
||||
UnixSocketClient unixSocketClient;
|
||||
ServiceBase serviceBase;
|
||||
ASSERT_TRUE(!unixSocketClient.Connect("asdf", serviceBase));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Start unixSocket Server.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesIpcTest, UnixSocketServer, TestSize.Level1)
|
||||
{
|
||||
UnixSocketServer unixSocketServer;
|
||||
|
||||
unixSocketServer.UnixSocketAccept(nullptr);
|
||||
|
||||
ServiceEntry serviceEntry;
|
||||
ASSERT_TRUE(unixSocketServer.StartServer("", serviceEntry));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Server process monitoring.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesIpcTest, ServiceEntry, TestSize.Level1)
|
||||
{
|
||||
ServiceEntry serviceEntry;
|
||||
IPluginServiceServer pluginService;
|
||||
serviceEntry.StartServer("test_unix_socket_service_entry");
|
||||
serviceEntry.RegisterService(pluginService);
|
||||
serviceEntry.FindServiceByName(pluginService.serviceName_);
|
||||
|
||||
std::this_thread::sleep_for(TEMP_DELAY);
|
||||
|
||||
GetTimeMS();
|
||||
GetTimeUS();
|
||||
GetTimeNS();
|
||||
|
||||
IPluginServiceClient pluginClient;
|
||||
ASSERT_FALSE(pluginClient.Connect(""));
|
||||
std::this_thread::sleep_for(TEMP_DELAY);
|
||||
}
|
||||
} // namespace
|
80
device/plugins/api/test/unittest/services_plugin_service_test.cpp
Executable file
80
device/plugins/api/test/unittest/services_plugin_service_test.cpp
Executable file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
|
||||
#include "plugin_service.h"
|
||||
#include "plugin_session.h"
|
||||
#include "profiler_data_repeater.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using PluginServicePtr = STD_PTR(shared, PluginService);
|
||||
|
||||
class ServicesPluginServiceTest : public ::testing::Test {
|
||||
protected:
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Session flow test, get session id by plugin name.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesPluginServiceTest, PluginService1, TestSize.Level1)
|
||||
{
|
||||
PluginServicePtr pluginService = std::make_shared<PluginService>();
|
||||
ProfilerPluginConfig ppc;
|
||||
ppc.set_name("abc.so");
|
||||
ppc.set_plugin_sha256("ASDFAADSF");
|
||||
ppc.set_sample_interval(20);
|
||||
|
||||
pluginService->CreatePluginSession(ppc, std::make_shared<ProfilerDataRepeater>(4096));
|
||||
pluginService->StartPluginSession(ppc);
|
||||
pluginService->StopPluginSession("abc.so");
|
||||
pluginService->DestroyPluginSession("abc.so");
|
||||
pluginService->GetPluginIdByName("abc.so");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Session flow test, get plugin status.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesPluginServiceTest, PluginService2, TestSize.Level1)
|
||||
{
|
||||
PluginServicePtr pluginService = std::make_shared<PluginService>();
|
||||
ProfilerPluginConfig ppc;
|
||||
ppc.set_name("abc.so");
|
||||
ppc.set_plugin_sha256("ASDFAADSF");
|
||||
ppc.set_sample_interval(20);
|
||||
|
||||
ProfilerSessionConfig::BufferConfig bc;
|
||||
bc.set_pages(1);
|
||||
bc.set_policy(ProfilerSessionConfig_BufferConfig_Policy_RECYCLE);
|
||||
|
||||
pluginService->CreatePluginSession(ppc, bc, std::make_shared<ProfilerDataRepeater>(4096));
|
||||
pluginService->StartPluginSession(ppc);
|
||||
pluginService->StopPluginSession("abc.so");
|
||||
pluginService->GetPluginStatus();
|
||||
|
||||
PluginInfo pi;
|
||||
pi.id = 0;
|
||||
pi.name = "abc.so";
|
||||
pi.path = "abc.so";
|
||||
pi.sha256 = "asdfasdf";
|
||||
pluginService->RemovePluginInfo(pi);
|
||||
}
|
@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugin_service.h"
|
||||
#include "plugin_session.h"
|
||||
#include "profiler_capability_manager.h"
|
||||
#include "profiler_data_repeater.h"
|
||||
#include "profiler_service.h"
|
||||
#include "result_demuxer.h"
|
||||
#include "trace_file_reader.h"
|
||||
#include "trace_file_writer.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
const std::string DEFAULT_TEST_PATH("./");
|
||||
#else
|
||||
const std::string DEFAULT_TEST_PATH("/data/local/tmp/");
|
||||
#endif
|
||||
|
||||
using PluginServicePtr = STD_PTR(shared, PluginService);
|
||||
using ProfilerDataRepeaterPtr = STD_PTR(shared, ProfilerDataRepeater);
|
||||
using ProfilerServicePtr = STD_PTR(shared, ProfilerService);
|
||||
using ProfilerPluginDataPtr = STD_PTR(shared, ProfilerPluginData);
|
||||
|
||||
constexpr int DATA_MAX_SIZE = 10;
|
||||
|
||||
class ServicesProfilerServiceTest : public ::testing::Test {
|
||||
protected:
|
||||
ProfilerPluginConfig config;
|
||||
ProfilerSessionConfig::BufferConfig bufferConfig;
|
||||
PluginInfo pluginInfo;
|
||||
PluginServicePtr service;
|
||||
ProfilerDataRepeaterPtr repeater;
|
||||
ProfilerServicePtr service_;
|
||||
std::unique_ptr<grpc::ServerContext> context_;
|
||||
std::atomic<int> requestCounter{0};
|
||||
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
config.set_name("test_session");
|
||||
bufferConfig.set_pages(0);
|
||||
pluginInfo.name = config.name();
|
||||
service = std::make_shared<PluginService>();
|
||||
repeater = std::make_shared<ProfilerDataRepeater>(DATA_MAX_SIZE);
|
||||
if (service) {
|
||||
service->AddPluginInfo(pluginInfo);
|
||||
}
|
||||
|
||||
service_ = std::make_shared<ProfilerService>(service);
|
||||
context_ = std::make_unique<grpc::ServerContext>();
|
||||
}
|
||||
void TearDown() override
|
||||
{
|
||||
if (service) {
|
||||
service->RemovePluginInfo(pluginInfo);
|
||||
}
|
||||
ProfilerCapabilityManager::GetInstance().pluginCapabilities_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Plugin session flow test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, PluginSession, TestSize.Level1)
|
||||
{
|
||||
auto session = std::make_shared<PluginSession>(config, nullptr, nullptr);
|
||||
EXPECT_NE(session, nullptr);
|
||||
EXPECT_FALSE(session->IsAvailable());
|
||||
|
||||
EXPECT_FALSE(session->Create());
|
||||
config.set_name("test_session2");
|
||||
session = std::make_shared<PluginSession>(config, service, repeater);
|
||||
repeater->Size();
|
||||
|
||||
session.reset();
|
||||
config.set_name("test_session3");
|
||||
session = std::make_shared<PluginSession>(config, service, repeater);
|
||||
|
||||
ASSERT_NE(session->GetState(), PluginSession::CREATED);
|
||||
EXPECT_FALSE(session->Start());
|
||||
ASSERT_NE(session->GetState(), PluginSession::STARTED);
|
||||
EXPECT_FALSE(session->Stop());
|
||||
ASSERT_NE(session->GetState(), PluginSession::CREATED);
|
||||
EXPECT_FALSE(session->Destroy());
|
||||
EXPECT_EQ(session->GetState(), PluginSession::INITIAL);
|
||||
|
||||
// recreate is OK
|
||||
EXPECT_FALSE(session->Create());
|
||||
EXPECT_FALSE(session->Destroy());
|
||||
repeater->Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Streaming session test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, TraceFileWriter, TestSize.Level1)
|
||||
{
|
||||
std::string path = "trace.bin";
|
||||
auto writer = std::make_shared<TraceFileWriter>(path);
|
||||
EXPECT_NE(writer, nullptr);
|
||||
|
||||
std::string testData = "Hello, Wrold!";
|
||||
EXPECT_EQ(writer->Write(testData.data(), testData.size()), sizeof(uint32_t) + testData.size());
|
||||
EXPECT_EQ(writer->Flush(), true);
|
||||
|
||||
ProfilerPluginData pluginData;
|
||||
pluginData.set_name("ABC");
|
||||
pluginData.set_status(0);
|
||||
pluginData.set_data("DEF");
|
||||
EXPECT_GT(writer->Write(pluginData), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Streaming session test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, TraceFileReader, TestSize.Level1)
|
||||
{
|
||||
std::string path = "trace-write-msg.bin";
|
||||
auto writer = std::make_shared<TraceFileWriter>(path);
|
||||
ASSERT_NE(writer, nullptr);
|
||||
|
||||
constexpr int n = 100;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
ProfilerPluginData pluginData{};
|
||||
pluginData.set_name("test_name");
|
||||
pluginData.set_status(i);
|
||||
pluginData.set_data("Hello, Wrold!");
|
||||
long bytes = writer->Write(pluginData);
|
||||
EXPECT_EQ(bytes, sizeof(uint32_t) + pluginData.ByteSizeLong());
|
||||
HILOG_INFO(LOG_CORE, "[%d/%d] write %ld bytes to %s.", i, n, bytes, path.c_str());
|
||||
}
|
||||
writer.reset(); // make sure write done!
|
||||
|
||||
auto reader = std::make_shared<TraceFileReader>();
|
||||
ASSERT_NE(reader, nullptr);
|
||||
ASSERT_TRUE(reader->Open(path));
|
||||
for (int i = 1; i <= n; i++) {
|
||||
ProfilerPluginData data{};
|
||||
long bytes = reader->Read(data);
|
||||
HILOG_INFO(LOG_CORE, "data = {%s, %d, %s}", data.name().c_str(), data.status(), data.data().c_str());
|
||||
HILOG_INFO(LOG_CORE, "read %ld bytes from %s", bytes, path.c_str());
|
||||
}
|
||||
|
||||
ASSERT_TRUE(reader->Open(path));
|
||||
long bytes = 0;
|
||||
do {
|
||||
ProfilerPluginData data{};
|
||||
bytes = reader->Read(data);
|
||||
HILOG_INFO(LOG_CORE, "data = {%s, %d, %s}", data.name().c_str(), data.status(), data.data().c_str());
|
||||
HILOG_INFO(LOG_CORE, "read %ld bytes from %s", bytes, path.c_str());
|
||||
} while (bytes > 0);
|
||||
|
||||
ASSERT_EQ(reader->Read(nullptr, 0), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: service
|
||||
* @tc.desc: Streaming session report result test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, ResultDemuxer1, TestSize.Level1)
|
||||
{
|
||||
std::string path = "demux.bin";
|
||||
ProfilerDataRepeaterPtr repeater = std::make_shared<ProfilerDataRepeater>(DATA_MAX_SIZE);
|
||||
|
||||
auto demuxer = std::make_shared<ResultDemuxer>(repeater);
|
||||
EXPECT_NE(demuxer, nullptr);
|
||||
demuxer->SetTraceWriter(nullptr);
|
||||
|
||||
auto writer = std::make_shared<TraceFileWriter>(path);
|
||||
EXPECT_NE(writer, nullptr);
|
||||
demuxer->SetTraceWriter(writer);
|
||||
|
||||
const int putCount = 20;
|
||||
const int putDelayUs = 10 * 1000;
|
||||
demuxer->StartTakeResults();
|
||||
std::thread dataProducer([=] {
|
||||
for (int i = 0; i < putCount; i++) {
|
||||
auto pluginData = std::make_shared<ProfilerPluginData>();
|
||||
ASSERT_NE(pluginData, nullptr);
|
||||
pluginData->set_name("test-" + std::to_string(i));
|
||||
pluginData->set_status(i);
|
||||
repeater->PutPluginData(pluginData);
|
||||
HILOG_DEBUG(LOG_CORE, "put test data %d...", i);
|
||||
usleep(putDelayUs);
|
||||
}
|
||||
repeater->PutPluginData(nullptr);
|
||||
});
|
||||
|
||||
HILOG_DEBUG(LOG_CORE, "wating producer thread done...");
|
||||
dataProducer.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: service
|
||||
* @tc.desc: Streaming session report result test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, ResultDemuxer2, TestSize.Level1)
|
||||
{
|
||||
std::string path = "demux.bin";
|
||||
ProfilerDataRepeaterPtr repeater = std::make_shared<ProfilerDataRepeater>(DATA_MAX_SIZE);
|
||||
|
||||
auto demuxer = std::make_shared<ResultDemuxer>(repeater);
|
||||
ASSERT_NE(demuxer, nullptr);
|
||||
|
||||
auto writer = std::make_shared<TraceFileWriter>(path);
|
||||
EXPECT_NE(writer, nullptr);
|
||||
demuxer->SetTraceWriter(writer);
|
||||
|
||||
const int putCount = 30;
|
||||
const int putDelayUs = 10 * 1000;
|
||||
demuxer->StartTakeResults();
|
||||
std::thread dataProducer([=] {
|
||||
for (int i = 0; i < putCount; i++) {
|
||||
auto pluginData = std::make_shared<ProfilerPluginData>();
|
||||
ASSERT_NE(pluginData, nullptr);
|
||||
pluginData->set_name("AB-" + std::to_string(i));
|
||||
pluginData->set_status(i);
|
||||
|
||||
HILOG_DEBUG(LOG_CORE, "put test data %d...", i);
|
||||
if (!repeater->PutPluginData(pluginData)) {
|
||||
HILOG_WARN(LOG_CORE, "put test data %d FAILED!", i);
|
||||
break;
|
||||
}
|
||||
usleep(putDelayUs);
|
||||
}
|
||||
});
|
||||
|
||||
usleep((putCount / 2) * putDelayUs);
|
||||
demuxer->StopTakeResults();
|
||||
|
||||
repeater->Close();
|
||||
HILOG_DEBUG(LOG_CORE, "wating producer thread done...");
|
||||
dataProducer.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: server
|
||||
* @tc.desc: Profiler capacity management.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, ProfilerCapabilityManager, TestSize.Level1)
|
||||
{
|
||||
std::vector<ProfilerPluginCapability> caps = ProfilerCapabilityManager::GetInstance().GetCapabilities();
|
||||
for (int i = 0; i < caps.size(); i++) {
|
||||
auto cap = caps[i];
|
||||
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(cap.name()));
|
||||
}
|
||||
caps.clear();
|
||||
|
||||
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapability("xxx"), nullptr);
|
||||
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapabilities().size(), 0);
|
||||
|
||||
caps = ProfilerCapabilityManager::GetInstance().GetCapabilities();
|
||||
EXPECT_EQ(caps.size(), 0);
|
||||
|
||||
const int n = 10;
|
||||
for (int i = 0; i < n; i++) {
|
||||
ProfilerPluginCapability cap;
|
||||
cap.set_path("/system/lib/libcap_" + std::to_string(i) + ".so");
|
||||
cap.set_name("cap_" + std::to_string(i));
|
||||
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().AddCapability(cap));
|
||||
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapabilities().size(), i + 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
ProfilerPluginCapability cap;
|
||||
cap.set_name("cap_" + std::to_string(i));
|
||||
auto capPtr = ProfilerCapabilityManager::GetInstance().GetCapability(cap.name());
|
||||
ASSERT_NE(capPtr, nullptr);
|
||||
EXPECT_EQ(capPtr->name(), cap.name());
|
||||
}
|
||||
|
||||
ProfilerPluginCapability cap1;
|
||||
cap1.set_path("/system/lib/libcap1.so");
|
||||
cap1.set_name("cap1");
|
||||
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().AddCapability(cap1));
|
||||
|
||||
cap1.set_path("/system/lib/libcap2.so");
|
||||
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().UpdateCapability(cap1.name(), cap1));
|
||||
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(cap1.name()));
|
||||
|
||||
caps = ProfilerCapabilityManager::GetInstance().GetCapabilities();
|
||||
EXPECT_EQ(caps.size(), n);
|
||||
for (int i = 0; i < caps.size(); i++) {
|
||||
auto cap = caps[i];
|
||||
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(cap.name()));
|
||||
|
||||
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapabilities().size(), n - (i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: server
|
||||
* @tc.desc: Profiler data repeater.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, ProfilerDataRepeater, TestSize.Level1)
|
||||
{
|
||||
const int itemCounts = 10000;
|
||||
const int bufferSize = itemCounts;
|
||||
auto inDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
|
||||
ASSERT_NE(inDataRepeater, nullptr);
|
||||
|
||||
auto outDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
|
||||
ASSERT_NE(outDataRepeater, nullptr);
|
||||
|
||||
auto f = [](int x) { return 2 * x + 1; };
|
||||
std::thread worker([&]() {
|
||||
for (int i = 0; i < itemCounts; i++) {
|
||||
auto xData = inDataRepeater->TakePluginData();
|
||||
|
||||
// compute in worker thread
|
||||
int x = xData ? std::stoi(xData->data()) : 0;
|
||||
int y = f(x);
|
||||
|
||||
auto yData = std::make_shared<ProfilerPluginData>();
|
||||
yData->set_data(std::to_string(y));
|
||||
outDataRepeater->PutPluginData(yData);
|
||||
}
|
||||
});
|
||||
|
||||
std::vector<int> yVec;
|
||||
for (int i = 0; i < itemCounts; i++) {
|
||||
int x0 = i;
|
||||
auto xData = std::make_shared<ProfilerPluginData>();
|
||||
xData->set_data(std::to_string(x0));
|
||||
inDataRepeater->PutPluginData(xData);
|
||||
|
||||
int y0 = f(x0);
|
||||
yVec.push_back(y0);
|
||||
}
|
||||
worker.join();
|
||||
|
||||
std::vector<ProfilerPluginDataPtr> pluginDataVec;
|
||||
auto count = outDataRepeater->TakePluginData(pluginDataVec);
|
||||
EXPECT_EQ(count, yVec.size());
|
||||
|
||||
for (size_t i = 0; i < pluginDataVec.size(); i++) {
|
||||
auto yData = pluginDataVec[i];
|
||||
int y = yData ? std::stoi(yData->data()) : 0;
|
||||
EXPECT_EQ(y, yVec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: server
|
||||
* @tc.desc: Session flow test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, ProfilerService1, TestSize.Level1)
|
||||
{
|
||||
ASSERT_NE(service_, nullptr);
|
||||
ASSERT_NE(context_, nullptr);
|
||||
|
||||
GetCapabilitiesRequest request;
|
||||
GetCapabilitiesResponse response;
|
||||
|
||||
ProfilerPluginCapability cap;
|
||||
cap.set_name("cap1");
|
||||
ProfilerCapabilityManager::GetInstance().AddCapability(cap);
|
||||
|
||||
request.set_request_id(++requestCounter);
|
||||
auto status = service_->GetCapabilities(context_.get(), &request, &response);
|
||||
EXPECT_EQ(status.error_code(), grpc::StatusCode::OK);
|
||||
EXPECT_GT(response.capabilities_size(), 0);
|
||||
HILOG_DEBUG(LOG_CORE, "GetCapabilities, capabilities_size = %d", response.capabilities_size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: server
|
||||
* @tc.desc: Session flow test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesProfilerServiceTest, ProfilerService2, TestSize.Level1)
|
||||
{
|
||||
ASSERT_NE(service_, nullptr);
|
||||
ASSERT_NE(context_, nullptr);
|
||||
|
||||
CreateSessionRequest request;
|
||||
CreateSessionResponse response;
|
||||
|
||||
auto status = service_->CreateSession(context_.get(), &request, &response);
|
||||
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
|
||||
|
||||
StartSessionRequest startrequest;
|
||||
StartSessionResponse startresponse;
|
||||
startrequest.set_session_id(0);
|
||||
startrequest.set_request_id(++requestCounter);
|
||||
status = service_->StartSession(context_.get(), &startrequest, &startresponse);
|
||||
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
|
||||
|
||||
StopSessionRequest stoprequest;
|
||||
StopSessionResponse stopresponse;
|
||||
stoprequest.set_session_id(0);
|
||||
stoprequest.set_request_id(++requestCounter);
|
||||
status = service_->StopSession(context_.get(), &stoprequest, &stopresponse);
|
||||
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
|
||||
|
||||
DestroySessionRequest destroyrequest;
|
||||
DestroySessionResponse destroyresponse;
|
||||
destroyrequest.set_session_id(0);
|
||||
destroyrequest.set_request_id(++requestCounter);
|
||||
status = service_->DestroySession(context_.get(), &destroyrequest, &destroyresponse);
|
||||
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
|
||||
}
|
||||
} // namespace
|
86
device/plugins/api/test/unittest/services_shared_memory_test.cpp
Executable file
86
device/plugins/api/test/unittest/services_shared_memory_test.cpp
Executable file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
#include <thread>
|
||||
|
||||
#include "plugin_service_types.pb.h"
|
||||
#include "share_memory_allocator.h"
|
||||
#include "share_memory_block.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
class ServicesSharedMemoryTest : public ::testing::Test {
|
||||
protected:
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: server
|
||||
* @tc.desc: Shared memory flow test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesSharedMemoryTest, SharedMemoryBlock, TestSize.Level1)
|
||||
{
|
||||
ShareMemoryBlock shareMemoryBlock;
|
||||
ASSERT_TRUE(shareMemoryBlock.CreateBlock("testname", 1024));
|
||||
|
||||
shareMemoryBlock.GetName();
|
||||
shareMemoryBlock.GetSize();
|
||||
shareMemoryBlock.GetfileDescriptor();
|
||||
|
||||
shareMemoryBlock.SetDropType(ShareMemoryBlock::DropType::DROP_NONE);
|
||||
int8_t data[100];
|
||||
for (int i = 0; i < 20; i++) {
|
||||
*((uint32_t*)data) = i;
|
||||
shareMemoryBlock.PutRaw(data, 100);
|
||||
}
|
||||
int8_t* p = shareMemoryBlock.GetFreeMemory(100);
|
||||
ASSERT_TRUE(p == nullptr);
|
||||
do {
|
||||
p = const_cast<int8_t*>(shareMemoryBlock.GetDataPoint());
|
||||
printf("%p,p=%d\n", p, *((int*)p));
|
||||
} while (shareMemoryBlock.Next() && shareMemoryBlock.GetDataSize() > 0);
|
||||
|
||||
NotifyResultResponse response;
|
||||
response.set_status(123);
|
||||
ASSERT_TRUE(shareMemoryBlock.PutProtobuf(response));
|
||||
ASSERT_TRUE(shareMemoryBlock.GetDataSize() > 0);
|
||||
response.ParseFromArray(shareMemoryBlock.GetDataPoint(), shareMemoryBlock.GetDataSize());
|
||||
ASSERT_TRUE(response.status() == 123);
|
||||
|
||||
ASSERT_TRUE(shareMemoryBlock.ReleaseBlock());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: server
|
||||
* @tc.desc: Shared memory abnormal flow test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ServicesSharedMemoryTest, SharedMemoryAllocator, TestSize.Level1)
|
||||
{
|
||||
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("testname", 1) ==
|
||||
nullptr); // 创建内存块大小<1024,返回空
|
||||
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("testname", 1024) != nullptr); // 成功创建
|
||||
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("testname", 1024) ==
|
||||
nullptr); // 创建同名内存块返回空
|
||||
|
||||
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal("testname"));
|
||||
ASSERT_FALSE(ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal("or")); // 释放不存在的内存块返回-1
|
||||
}
|
||||
} // namespace
|
52
device/plugins/api/test/unittest/writer_adapter_test.cpp
Executable file
52
device/plugins/api/test/unittest/writer_adapter_test.cpp
Executable file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "writer_adapter.h"
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
class WriterAdapterTest : public ::testing::Test {
|
||||
protected:
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Write data to shared memory through writer.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(WriterAdapterTest, Writer, TestSize.Level1)
|
||||
{
|
||||
WriterAdapter writerAdapter;
|
||||
writerAdapter.GetWriter();
|
||||
writerAdapter.GetStruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: plugin
|
||||
* @tc.desc: Write data to shared memory through writer.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(WriterAdapterTest, Func, TestSize.Level1)
|
||||
{
|
||||
WriterAdapter writerAdapter;
|
||||
writerAdapter.WriteFunc(nullptr, nullptr, 0);
|
||||
writerAdapter.FlushFunc(nullptr);
|
||||
}
|
||||
} // namespace
|
61
device/plugins/bytrace_plugin/BUILD.gn
Executable file
61
device/plugins/bytrace_plugin/BUILD.gn
Executable file
@ -0,0 +1,61 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../../base/config.gni")
|
||||
|
||||
config("bytraceplugin_config") {
|
||||
include_dirs = [
|
||||
"../api/include",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
"../../services/profiler_service/src",
|
||||
"../../base/include",
|
||||
"include",
|
||||
"//utils/native/base/include",
|
||||
]
|
||||
}
|
||||
|
||||
ohos_shared_library("bytraceplugin") {
|
||||
output_name = "bytraceplugin"
|
||||
sources = [
|
||||
"src/bytrace_module.cpp",
|
||||
]
|
||||
public_configs = [ ":bytraceplugin_config" ]
|
||||
public_deps = [
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/bytrace_plugin:bytrace_plugin_protos_cpp",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
|
||||
]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
if (build_l2) {
|
||||
external_deps = [ "shared_library:libhilog" ]
|
||||
} else {
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
}
|
||||
}
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
||||
|
||||
ohos_executable("test_bytraceplugin") {
|
||||
output_name = "test_bytraceplugin"
|
||||
sources = [
|
||||
"src/run_test.cpp",
|
||||
]
|
||||
deps = [
|
||||
":bytraceplugin",
|
||||
]
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
27
device/plugins/bytrace_plugin/include/bytrace_module.h
Executable file
27
device/plugins/bytrace_plugin/include/bytrace_module.h
Executable file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BYTRACE_MODULE_H
|
||||
#define BYTRACE_MODULE_H
|
||||
|
||||
#include "plugin_module_api.h"
|
||||
|
||||
int BytracePluginSessionStart(const uint8_t* configData, const uint32_t configSize);
|
||||
|
||||
int BytraceRegisterWriterStruct(WriterStruct* writer);
|
||||
|
||||
int BytracePluginSessionStop();
|
||||
|
||||
#endif // BYTRACE_MODULE_H
|
135
device/plugins/bytrace_plugin/src/bytrace_module.cpp
Normal file
135
device/plugins/bytrace_plugin/src/bytrace_module.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytrace_module.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include "bytrace_plugin_config.pb.h"
|
||||
#include "logging.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace {
|
||||
const std::string CMD_PATH = "/system/bin/bytrace";
|
||||
int g_processNum = -1;
|
||||
constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
|
||||
|
||||
bool RunWithConfig(const BytracePluginConfig& config)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
args.push_back("bytrace");
|
||||
if (config.buffe_size() != 0) {
|
||||
args.push_back("-b");
|
||||
args.push_back(std::to_string(config.buffe_size()));
|
||||
}
|
||||
if (config.time() != 0) {
|
||||
args.push_back("-t");
|
||||
args.push_back(std::to_string(config.time()));
|
||||
}
|
||||
if (!config.clock().empty()) {
|
||||
args.push_back("--trace_clock");
|
||||
args.push_back(config.clock());
|
||||
}
|
||||
if (!config.outfile_name().empty()) {
|
||||
args.push_back("-o");
|
||||
args.push_back(config.outfile_name());
|
||||
}
|
||||
if (!config.categories().empty()) {
|
||||
for (std::string category : config.categories()) {
|
||||
args.push_back(category);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char*> params;
|
||||
std::string cmdPrintStr = "";
|
||||
for (std::string& it : args) {
|
||||
cmdPrintStr += (it + " ");
|
||||
params.push_back(const_cast<char*>(it.c_str()));
|
||||
}
|
||||
params.push_back(nullptr);
|
||||
HILOG_INFO(LOG_CORE, "call bytrace::Run: %s", cmdPrintStr.c_str());
|
||||
|
||||
execv(CMD_PATH.data(), ¶ms[0]);
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int BytracePluginSessionStart(const uint8_t* configData, const uint32_t configSize)
|
||||
{
|
||||
BytracePluginConfig config;
|
||||
HILOG_INFO(LOG_CORE, "BytracePluginSessionStart %u", configSize);
|
||||
CHECK_TRUE(config.ParseFromArray(configData, configSize), 0, "parse config FAILED!");
|
||||
|
||||
g_processNum = fork();
|
||||
CHECK_TRUE(g_processNum >= 0, -1, "create process FAILED!");
|
||||
|
||||
if (g_processNum == 0) {
|
||||
// child process
|
||||
CHECK_TRUE(RunWithConfig(config), 0, "run bytrace FAILED!");
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BytraceRegisterWriterStruct(const WriterStruct* writer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BytracePluginSessionStop()
|
||||
{
|
||||
if (g_processNum > 0) {
|
||||
// parent process
|
||||
int status = 0;
|
||||
// judge if child process have exited.
|
||||
if (waitpid(g_processNum, &status, WNOHANG) == 0) {
|
||||
// send SIGKILL to child process.
|
||||
if (kill(g_processNum, SIGINT)) {
|
||||
HILOG_WARN(LOG_CORE, "BytracePluginSessionStop kill child process failed.");
|
||||
} else {
|
||||
HILOG_INFO(LOG_CORE, "BytracePluginSessionStop kill child process success.");
|
||||
}
|
||||
}
|
||||
// report child process exit status.
|
||||
if (WIFEXITED(status)) {
|
||||
HILOG_INFO(LOG_CORE, "child %d exit with status %d!", g_processNum,
|
||||
WEXITSTATUS(static_cast<unsigned>(status)));
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
HILOG_INFO(LOG_CORE, "child %d exit with signal %d!", g_processNum,
|
||||
WTERMSIG(static_cast<unsigned>(status)));
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
HILOG_INFO(LOG_CORE, "child %d stopped by signal %d", g_processNum,
|
||||
WSTOPSIG(static_cast<unsigned>(status)));
|
||||
} else {
|
||||
HILOG_INFO(LOG_CORE, "child %d otherwise", g_processNum);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PluginModuleCallbacks g_callbacks = {
|
||||
BytracePluginSessionStart,
|
||||
nullptr, // onPluginReportResult
|
||||
BytracePluginSessionStop,
|
||||
BytraceRegisterWriterStruct,
|
||||
};
|
||||
|
||||
PluginModuleStruct g_pluginModule = {&g_callbacks, "bytrace_plugin", MAX_BUFFER_SIZE};
|
45
device/plugins/bytrace_plugin/src/run_test.cpp
Normal file
45
device/plugins/bytrace_plugin/src/run_test.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytrace_module.h"
|
||||
#include "bytrace_plugin_config.pb.h"
|
||||
#include "logging.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t TRACE_TIME = 8;
|
||||
constexpr uint32_t WAIT_TIME = 9;
|
||||
constexpr uint32_t BUFFE_SIZE = 1024;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
WriterStruct writer;
|
||||
BytraceRegisterWriterStruct(&writer);
|
||||
|
||||
BytracePluginConfig config;
|
||||
config.set_clock("boot");
|
||||
config.set_time(TRACE_TIME);
|
||||
config.set_buffe_size(BUFFE_SIZE);
|
||||
config.set_outfile_name("/data/local/tmp/bytrace.txt");
|
||||
config.add_categories("sched");
|
||||
|
||||
std::vector<char> buffer(config.ByteSizeLong());
|
||||
CHECK_TRUE(config.SerializeToArray(buffer.data(), buffer.size()), 0, "Serialize config FAILED!");
|
||||
CHECK_TRUE(BytracePluginSessionStart(reinterpret_cast<uint8_t*>(buffer.data()), buffer.size()) == 0, 0,
|
||||
"call start callback FAILED!");
|
||||
sleep(WAIT_TIME);
|
||||
BytracePluginSessionStop();
|
||||
return 0;
|
||||
}
|
49
device/plugins/memory_plugin/BUILD.gn
Executable file
49
device/plugins/memory_plugin/BUILD.gn
Executable file
@ -0,0 +1,49 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../../base/config.gni")
|
||||
|
||||
ohos_shared_library("memdataplugin") {
|
||||
output_name = "memdataplugin"
|
||||
sources = [
|
||||
"src/buffer_splitter.cpp",
|
||||
"src/memory_data_plugin.cpp",
|
||||
"src/memory_module.cpp",
|
||||
"src/smaps_stats.cpp",
|
||||
]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"../api/include",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
"${OHOS_PROFILER_DIR}/device/base/include",
|
||||
"//utils/native/base/include",
|
||||
]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/memory_data:memory_data_cpp",
|
||||
"//utils/native/base:utilsbase",
|
||||
]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
if (build_l2) {
|
||||
external_deps = [ "shared_library:libhilog" ]
|
||||
} else {
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
}
|
||||
}
|
||||
public_configs = [ "${OHOS_PROFILER_DIR}/device/base:hiprofiler_test_config" ]
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
69
device/plugins/memory_plugin/include/buffer_splitter.h
Executable file
69
device/plugins/memory_plugin/include/buffer_splitter.h
Executable file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BUFFER_SPLITTER_H_
|
||||
#define _BUFFER_SPLITTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Description: Buffer Splitter Class
|
||||
* The BufferSplitter class object splits the buffer content by moving the pointer
|
||||
* Except for the last character, other buffer contents are not modified during the segmentation
|
||||
*/
|
||||
|
||||
class BufferSplitter {
|
||||
public:
|
||||
/* During construction, buf[size-1] will be forcibly modified to '\ 0'
|
||||
The constructor will automatically call the NextLine to initialize the first line of data */
|
||||
BufferSplitter(const char* buf, int size);
|
||||
|
||||
~BufferSplitter() {}
|
||||
/* Find and update the next line header pointer, and line length. Length does not include '\ n' and '\ 0' */
|
||||
bool NextLine();
|
||||
|
||||
/* Find and update the NextWord's head pointer and Word length according to the delimiter within the
|
||||
current line range. The length calculation does not include the 'delimiter' */
|
||||
/* When the current line cannot find a specific 'delimiter', it can
|
||||
be split from the current position according to the new 'delimiter' */
|
||||
bool NextWord(char delimiter);
|
||||
|
||||
const char* CurWord()
|
||||
{
|
||||
return curWord_;
|
||||
}
|
||||
size_t CurWordSize() const
|
||||
{
|
||||
return curWordSize_;
|
||||
}
|
||||
char* CurLine()
|
||||
{
|
||||
return curLine_;
|
||||
}
|
||||
size_t CurLineSize() const
|
||||
{
|
||||
return curLineSize_;
|
||||
}
|
||||
|
||||
private:
|
||||
char* curWord_ = nullptr;
|
||||
size_t curWordSize_ = 0;
|
||||
char* next_;
|
||||
char* curLine_ = nullptr;
|
||||
size_t curLineSize_ = 0;
|
||||
char* nextLine_;
|
||||
char* end_;
|
||||
};
|
||||
#endif
|
171
device/plugins/memory_plugin/include/memory_data_plugin.h
Executable file
171
device/plugins/memory_plugin/include/memory_data_plugin.h
Executable file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_DATA_PLUGIN_H
|
||||
#define MEMORY_DATA_PLUGIN_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "logging.h"
|
||||
#include "memory_plugin_config.pb.h"
|
||||
#include "memory_plugin_result.pb.h"
|
||||
#include "smaps_stats.h"
|
||||
|
||||
struct Proto2StrMapping {
|
||||
int protobufid;
|
||||
const char* procstr;
|
||||
};
|
||||
|
||||
constexpr Proto2StrMapping meminfoMapping[] = {
|
||||
{SysMeminfoType::MEMINFO_UNSPECIFIED, "MemUnspecified"},
|
||||
{SysMeminfoType::MEMINFO_MEM_TOTAL, "MemTotal"},
|
||||
{SysMeminfoType::MEMINFO_MEM_FREE, "MemFree"},
|
||||
{SysMeminfoType::MEMINFO_MEM_AVAILABLE, "MemAvailable"},
|
||||
{SysMeminfoType::MEMINFO_BUFFERS, "Buffers"},
|
||||
{SysMeminfoType::MEMINFO_CACHED, "Cached"},
|
||||
{SysMeminfoType::MEMINFO_SWAP_CACHED, "SwapCached"},
|
||||
{SysMeminfoType::MEMINFO_ACTIVE, "Active"},
|
||||
{SysMeminfoType::MEMINFO_INACTIVE, "Inactive"},
|
||||
{SysMeminfoType::MEMINFO_ACTIVE_ANON, "Active(anon)"},
|
||||
{SysMeminfoType::MEMINFO_INACTIVE_ANON, "Inactive(anon)"},
|
||||
{SysMeminfoType::MEMINFO_ACTIVE_FILE, "Active(file)"},
|
||||
{SysMeminfoType::MEMINFO_INACTIVE_FILE, "Inactive(file)"},
|
||||
{SysMeminfoType::MEMINFO_UNEVICTABLE, "Unevictable"},
|
||||
{SysMeminfoType::MEMINFO_MLOCKED, "Mlocked"},
|
||||
{SysMeminfoType::MEMINFO_SWAP_TOTAL, "SwapTotal"},
|
||||
{SysMeminfoType::MEMINFO_SWAP_FREE, "SwapFree"},
|
||||
{SysMeminfoType::MEMINFO_DIRTY, "Dirty"},
|
||||
{SysMeminfoType::MEMINFO_WRITEBACK, "Writeback"},
|
||||
{SysMeminfoType::MEMINFO_ANON_PAGES, "AnonPages"},
|
||||
{SysMeminfoType::MEMINFO_MAPPED, "Mapped"},
|
||||
{SysMeminfoType::MEMINFO_SHMEM, "Shmem"},
|
||||
};
|
||||
|
||||
struct ProcStatusMapping {
|
||||
int procid;
|
||||
const char* procstr;
|
||||
};
|
||||
|
||||
enum StatusType {
|
||||
PRO_TGID = 1,
|
||||
PRO_NAME,
|
||||
PRO_VMSIZE,
|
||||
PRO_VMRSS,
|
||||
PRO_RSSANON,
|
||||
PRO_RSSFILE,
|
||||
PRO_RSSSHMEM,
|
||||
PRO_VMSWAP,
|
||||
PRO_VMLCK,
|
||||
PRO_VMHWM,
|
||||
};
|
||||
|
||||
constexpr ProcStatusMapping procStatusMapping[] = {
|
||||
{StatusType::PRO_TGID, "Tgid"}, {StatusType::PRO_NAME, "Name"}, {StatusType::PRO_VMSIZE, "VmSize"},
|
||||
{StatusType::PRO_VMRSS, "VmRSS"}, {StatusType::PRO_RSSANON, "RssAnon"}, {StatusType::PRO_RSSFILE, "RssFile"},
|
||||
{StatusType::PRO_RSSSHMEM, "RssShmem"}, {StatusType::PRO_VMSWAP, "VmSwap"}, {StatusType::PRO_VMLCK, "VmLck"},
|
||||
{StatusType::PRO_VMHWM, "VmHWM"},
|
||||
};
|
||||
|
||||
enum ErrorType {
|
||||
RET_NULL_ADDR,
|
||||
RET_IVALID_PID,
|
||||
RET_TGID_VALUE_NULL,
|
||||
RET_FAIL = -1,
|
||||
RET_SUCC = 0,
|
||||
};
|
||||
|
||||
enum FileType {
|
||||
FILE_STATUS = 0,
|
||||
FILE_OOM,
|
||||
FILE_SMAPS,
|
||||
};
|
||||
|
||||
struct ProcfdMapping {
|
||||
int procid;
|
||||
const char* file;
|
||||
};
|
||||
|
||||
constexpr ProcfdMapping procfdMapping[] = {
|
||||
{FileType::FILE_STATUS, "status"},
|
||||
{FileType::FILE_OOM, "oom_score_adj"},
|
||||
{FileType::FILE_SMAPS, "smaps"},
|
||||
};
|
||||
|
||||
class MemoryDataPlugin {
|
||||
public:
|
||||
MemoryDataPlugin();
|
||||
~MemoryDataPlugin();
|
||||
int Start(const uint8_t* configData, uint32_t configSize);
|
||||
int Report(uint8_t* configData, uint32_t configSize);
|
||||
int Stop();
|
||||
void SetPath(char* path)
|
||||
{
|
||||
testpath_ = path;
|
||||
};
|
||||
void WriteProcesseList(MemoryData& data);
|
||||
void WriteProcinfoByPidfds(ProcessMemoryInfo* processinfo, int32_t pid);
|
||||
DIR* OpenDestDir(const char* dirPath);
|
||||
int32_t GetValidPid(DIR* dirp);
|
||||
// for test change static
|
||||
int ParseNumber(std::string line);
|
||||
|
||||
private:
|
||||
/* data */
|
||||
MemoryConfig protoConfig_;
|
||||
|
||||
void* buffer_;
|
||||
int meminfoFd_;
|
||||
int vmstatFd_;
|
||||
std::map<std::string, int> meminfoCounters_;
|
||||
|
||||
void InitProto2StrVector();
|
||||
std::vector<const char*> meminfoStrList_;
|
||||
// SmapsStats *
|
||||
void WriteVmstat(MemoryData& data);
|
||||
void WriteMeminfo(MemoryData& data);
|
||||
|
||||
std::unordered_map<int32_t, std::vector<int>> pidFds_;
|
||||
std::vector<int32_t> seenPids_;
|
||||
char* testpath_;
|
||||
int32_t err_;
|
||||
int32_t ReadFile(int fd);
|
||||
std::vector<int> OpenProcPidFiles(int32_t pid);
|
||||
int32_t ReadProcPidFile(int32_t pid, const char* pFileName);
|
||||
void WriteProcessInfo(MemoryData& data, int32_t pid);
|
||||
void SetEmptyProcessInfo(ProcessMemoryInfo* processinfo);
|
||||
void WriteOomInfo(ProcessMemoryInfo* processinfo, int32_t pid);
|
||||
void WriteProcess(ProcessMemoryInfo* processinfo, const char* pFile, uint32_t fileLen, int32_t pid);
|
||||
void WriteAppsummary(ProcessMemoryInfo* processinfo, SmapsStats& smapInfo);
|
||||
void SetProcessInfo(ProcessMemoryInfo* processinfo, int key, const char* word);
|
||||
|
||||
bool BufnCmp(const char* src, int srcLen, const char* key, int keyLen);
|
||||
bool addPidBySort(int32_t pid);
|
||||
int GetProcStatusId(const char* src, int srcLen);
|
||||
|
||||
bool ParseMemInfo(const char* data, ProcessMemoryInfo* memoryInfo);
|
||||
bool GetMemInfoByDumpsys(uint32_t pid, ProcessMemoryInfo* memoryInfo);
|
||||
};
|
||||
|
||||
#endif
|
254
device/plugins/memory_plugin/include/smaps_stats.h
Executable file
254
device/plugins/memory_plugin/include/smaps_stats.h
Executable file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SMAPS_STATS_H
|
||||
#define SMAPS_STATS_H
|
||||
|
||||
#include "logging.h"
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <inttypes.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sys/mman.h>
|
||||
|
||||
struct stats_t {
|
||||
int pss;
|
||||
int swappablePss;
|
||||
int rss;
|
||||
int privateDirty;
|
||||
int sharedDirty;
|
||||
int privateClean;
|
||||
int sharedClean;
|
||||
int swappedOut;
|
||||
int swappedOutPss;
|
||||
};
|
||||
|
||||
enum NumType {
|
||||
FIFTH_FIELD = 5,
|
||||
HEX_BASE = 16,
|
||||
DEC_BASE = 10,
|
||||
};
|
||||
|
||||
struct MapPiecesInfo_t {
|
||||
uint64_t start_addr;
|
||||
uint64_t end_addr;
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct MemUsageInfo_t {
|
||||
uint64_t vss;
|
||||
uint64_t rss;
|
||||
uint64_t pss;
|
||||
uint64_t uss;
|
||||
|
||||
uint64_t swap;
|
||||
uint64_t swap_pss;
|
||||
|
||||
uint64_t private_clean;
|
||||
uint64_t private_dirty;
|
||||
uint64_t shared_clean;
|
||||
uint64_t shared_dirty;
|
||||
};
|
||||
|
||||
enum vmemifoType {
|
||||
VMHEAP_NULL = -2,
|
||||
VMHEAP_NEEDFIX = -1,
|
||||
VMHEAP_UNKNOWN,
|
||||
VMHEAP_DALVIK,
|
||||
VMHEAP_NATIVE,
|
||||
|
||||
VMHEAP_DALVIK_OTHER,
|
||||
VMHEAP_STACK,
|
||||
VMHEAP_CURSOR,
|
||||
VMHEAP_ASHMEM,
|
||||
VMHEAP_GL_DEV,
|
||||
VMHEAP_UNKNOWN_DEV,
|
||||
VMHEAP_SO,
|
||||
VMHEAP_JAR,
|
||||
VMHEAP_TTF,
|
||||
VMHEAP_DEX,
|
||||
VMHEAP_OAT,
|
||||
VMHEAP_ART,
|
||||
VMHEAP_UNKNOWN_MAP,
|
||||
VMHEAP_GRAPHICS,
|
||||
VMHEAP_GL,
|
||||
VMHEAP_OTHER_MEMTRACK,
|
||||
|
||||
// Dalvik extra sections (heap).
|
||||
VMHEAP_DALVIK_NORMAL,
|
||||
VMHEAP_DALVIK_LARGE,
|
||||
VMHEAP_DALVIK_ZYGOTE,
|
||||
VMHEAP_DALVIK_NON_MOVING,
|
||||
|
||||
// Dalvik other extra sections.
|
||||
VMHEAP_DALVIK_OTHER_LINEARALLOC,
|
||||
VMHEAP_DALVIK_OTHER_ACCOUNTING,
|
||||
VMHEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE,
|
||||
VMHEAP_DALVIK_OTHER_APP_CODE_CACHE,
|
||||
VMHEAP_DALVIK_OTHER_COMPILER_METADATA,
|
||||
VMHEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE,
|
||||
|
||||
// Boot vdex / app dex / app vdex
|
||||
VMHEAP_DEX_BOOT_VDEX,
|
||||
VMHEAP_DEX_APP_DEX,
|
||||
VMHEAP_DEX_APP_VDEX,
|
||||
|
||||
// App art, boot art.
|
||||
VMHEAP_ART_APP,
|
||||
VMHEAP_ART_BOOT,
|
||||
|
||||
_NUM_HEAP,
|
||||
_NUM_EXCLUSIVE_HEAP = VMHEAP_OTHER_MEMTRACK + 1,
|
||||
_NUM_CORE_HEAP = VMHEAP_NATIVE + 1
|
||||
};
|
||||
|
||||
enum OpsType {
|
||||
OPS_START = 1,
|
||||
OPS_END,
|
||||
};
|
||||
|
||||
struct vMeminfoAreaMapping {
|
||||
int ops;
|
||||
const char* heapstr;
|
||||
int heapid[2];
|
||||
};
|
||||
|
||||
constexpr vMeminfoAreaMapping vmaMemheap[] = {
|
||||
{OpsType::OPS_START, "[heap]", {vmemifoType::VMHEAP_NATIVE, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START, "[stack", {vmemifoType::VMHEAP_STACK, vmemifoType::VMHEAP_NULL}},
|
||||
};
|
||||
|
||||
// [anon:
|
||||
constexpr vMeminfoAreaMapping vmaMemanon[] = {
|
||||
{OpsType::OPS_START, "[anon:libc_malloc]", {vmemifoType::VMHEAP_NATIVE, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START, "[anon:scudo:", {vmemifoType::VMHEAP_NATIVE, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START, "[anon:GWP-ASan", {vmemifoType::VMHEAP_NATIVE, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START, "[anon:stack_and_tls:", {vmemifoType::VMHEAP_STACK, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-LinearAlloc",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_LINEARALLOC}},
|
||||
{OpsType::OPS_START, "[anon:dalvik-alloc space", {vmemifoType::VMHEAP_DALVIK, vmemifoType::VMHEAP_DALVIK_NORMAL}},
|
||||
{OpsType::OPS_START, "[anon:dalvik-main space", {vmemifoType::VMHEAP_DALVIK, vmemifoType::VMHEAP_DALVIK_NORMAL}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-large object space",
|
||||
{vmemifoType::VMHEAP_DALVIK, vmemifoType::VMHEAP_DALVIK_LARGE}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-free list large object space",
|
||||
{vmemifoType::VMHEAP_DALVIK, vmemifoType::VMHEAP_DALVIK_LARGE}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-non moving space",
|
||||
{vmemifoType::VMHEAP_DALVIK, vmemifoType::VMHEAP_DALVIK_NON_MOVING}},
|
||||
{OpsType::OPS_START, "[anon:dalvik-zygote space", {vmemifoType::VMHEAP_DALVIK, vmemifoType::VMHEAP_DALVIK_ZYGOTE}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-indirect ref",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-jit-code-cache",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_APP_CODE_CACHE}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-data-code-cache",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_APP_CODE_CACHE}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-CompilerMetadata",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_COMPILER_METADATA}},
|
||||
{OpsType::OPS_START,
|
||||
"[anon:dalvik-",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_ACCOUNTING}},
|
||||
{OpsType::OPS_START, "[anon:", {vmemifoType::VMHEAP_UNKNOWN, vmemifoType::VMHEAP_NULL}},
|
||||
};
|
||||
|
||||
constexpr vMeminfoAreaMapping vmaMemfd[] = {
|
||||
{OpsType::OPS_START,
|
||||
"/memfd:jit-cache",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_APP_CODE_CACHE}},
|
||||
{OpsType::OPS_START,
|
||||
"/memfd:jit-zygote-cache",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE}},
|
||||
};
|
||||
// dev
|
||||
constexpr vMeminfoAreaMapping vmaMemdev[] = {
|
||||
{OpsType::OPS_START, "/dev/kgsl-3d0", {vmemifoType::VMHEAP_GL_DEV, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START, "/dev/ashmem/CursorWindow", {vmemifoType::VMHEAP_CURSOR, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START,
|
||||
"/dev/ashmem/jit-zygote-cache",
|
||||
{vmemifoType::VMHEAP_DALVIK_OTHER, vmemifoType::VMHEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE}},
|
||||
{OpsType::OPS_START, "/dev/ashmem", {vmemifoType::VMHEAP_ASHMEM, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_START, "/dev/", {vmemifoType::VMHEAP_UNKNOWN_DEV, vmemifoType::VMHEAP_NULL}},
|
||||
};
|
||||
|
||||
constexpr vMeminfoAreaMapping vmaMemsuffix[] = {
|
||||
{OpsType::OPS_END, ".so", {vmemifoType::VMHEAP_SO, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_END, ".jar", {vmemifoType::VMHEAP_JAR, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_END, ".ttf", {vmemifoType::VMHEAP_TTF, vmemifoType::VMHEAP_NULL}},
|
||||
{OpsType::OPS_END, ".oat", {vmemifoType::VMHEAP_OAT, vmemifoType::VMHEAP_NULL}},
|
||||
|
||||
{OpsType::OPS_END, ".odex", {vmemifoType::VMHEAP_DEX, vmemifoType::VMHEAP_DEX_APP_DEX}},
|
||||
|
||||
{OpsType::OPS_END, ".vdex", {vmemifoType::VMHEAP_DEX, vmemifoType::VMHEAP_NEEDFIX}},
|
||||
{OpsType::OPS_END, ".art", {vmemifoType::VMHEAP_ART, vmemifoType::VMHEAP_NEEDFIX}},
|
||||
{OpsType::OPS_END, ".art]", {vmemifoType::VMHEAP_ART, vmemifoType::VMHEAP_NEEDFIX}},
|
||||
};
|
||||
|
||||
class SmapsStats {
|
||||
public:
|
||||
SmapsStats() {}
|
||||
SmapsStats(const std::string path) : testpath_(path){};
|
||||
~SmapsStats() {}
|
||||
bool ParseMaps(int pid);
|
||||
int GetProcessJavaHeap();
|
||||
int GetProcessNativeHeap();
|
||||
int GetProcessCode();
|
||||
int GetProcessStack();
|
||||
int GetProcessGraphics();
|
||||
int GetProcessPrivateOther();
|
||||
int GetProcessSystem();
|
||||
|
||||
private:
|
||||
stats_t stats_[_NUM_HEAP] = {{0}};
|
||||
bool lastline_ = false;
|
||||
std::string testpath_;
|
||||
|
||||
int GetTotalPrivateClean();
|
||||
int GetTotalPrivateDirty();
|
||||
int GetPrivate(int type);
|
||||
int GetTotalPss();
|
||||
int GetTotalSwappedOutPss();
|
||||
void ReviseStatsData();
|
||||
|
||||
bool ReadVmemareasFile(const std::string& path);
|
||||
bool ParseMapHead(std::string& line, MapPiecesInfo_t& head);
|
||||
bool SetMapAddrInfo(std::string& line, MapPiecesInfo_t& head);
|
||||
bool GetMemUsageField(std::string& line, MemUsageInfo_t& memusage);
|
||||
void CollectVmemAreasData(const MapPiecesInfo_t& mempic,
|
||||
const MemUsageInfo_t& memusage,
|
||||
uint64_t& prevEnd,
|
||||
int& prevHeap);
|
||||
bool GetVmaIndex(std::string name, uint32_t namesz, int32_t heapIndex[2], bool& swappable);
|
||||
uint64_t GetSwapablepssValue(const MemUsageInfo_t& memusage, bool swappable);
|
||||
void SetVmemAreasData(int index, uint64_t swapablePss, const MemUsageInfo_t& usage);
|
||||
void HeapIndexFix(std::string name, const char* key, int32_t heapIndex[2]);
|
||||
bool GetVMAStuId(int ops,
|
||||
std::string name,
|
||||
const vMeminfoAreaMapping* vma,
|
||||
int count,
|
||||
int32_t heapIndex[2],
|
||||
bool& swappable);
|
||||
};
|
||||
|
||||
#endif
|
99
device/plugins/memory_plugin/src/buffer_splitter.cpp
Executable file
99
device/plugins/memory_plugin/src/buffer_splitter.cpp
Executable file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "buffer_splitter.h"
|
||||
|
||||
BufferSplitter::BufferSplitter(const char* buf, int size)
|
||||
{
|
||||
next_ = const_cast<char*>(buf);
|
||||
nextLine_ = const_cast<char*>(buf);
|
||||
end_ = next_ + size;
|
||||
if (size) {
|
||||
next_[size - 1] = '\0';
|
||||
NextLine();
|
||||
}
|
||||
}
|
||||
|
||||
bool BufferSplitter::NextLine()
|
||||
{
|
||||
char delimiter = '\n';
|
||||
curLine_ = nullptr;
|
||||
curLineSize_ = 0;
|
||||
curWord_ = nullptr;
|
||||
curWordSize_ = 0;
|
||||
|
||||
if (next_ < end_) {
|
||||
next_ = nextLine_;
|
||||
}
|
||||
for (; next_ < end_; next_++) {
|
||||
if (*next_ == delimiter) {
|
||||
continue;
|
||||
}
|
||||
curLine_ = next_;
|
||||
while (true) {
|
||||
if (++next_ >= end_) {
|
||||
curLineSize_ = static_cast<size_t>(end_ - curLine_ - 1);
|
||||
next_ = curLine_;
|
||||
nextLine_ = end_;
|
||||
break;
|
||||
}
|
||||
if (*next_ == delimiter) {
|
||||
nextLine_ = ++next_;
|
||||
next_ = curLine_;
|
||||
curLineSize_ = static_cast<size_t>(nextLine_ - curLine_ - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curLineSize_ > 0) {
|
||||
return true;
|
||||
}
|
||||
curLine_ = nullptr;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BufferSplitter::NextWord(char delimiter)
|
||||
{
|
||||
char* nextBak = next_;
|
||||
curWord_ = nullptr;
|
||||
curWordSize_ = 0;
|
||||
|
||||
for (; next_ < nextLine_; next_++) {
|
||||
if (isspace(*next_) || *next_ == delimiter) {
|
||||
continue;
|
||||
}
|
||||
curWord_ = next_;
|
||||
while (true) {
|
||||
if (++next_ >= nextLine_) {
|
||||
curWordSize_ = 0;
|
||||
curWord_ = nullptr;
|
||||
next_ = nextBak;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*next_ == delimiter) {
|
||||
curWordSize_ = static_cast<size_t>(next_ - curWord_);
|
||||
++next_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curWordSize_ > 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
644
device/plugins/memory_plugin/src/memory_data_plugin.cpp
Normal file
644
device/plugins/memory_plugin/src/memory_data_plugin.cpp
Normal file
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "memory_data_plugin.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "buffer_splitter.h"
|
||||
#include "securec.h"
|
||||
#include "smaps_stats.h"
|
||||
|
||||
namespace {
|
||||
static const char* CMD_FORMAT = "dumpsys meminfo --local ";
|
||||
constexpr size_t READ_BUFFER_SIZE = 1024 * 16;
|
||||
static const int BUF_MAX_LEN = 2048;
|
||||
} // namespace
|
||||
|
||||
MemoryDataPlugin::MemoryDataPlugin()
|
||||
{
|
||||
buffer_ = nullptr;
|
||||
meminfoFd_ = -1;
|
||||
vmstatFd_ = -1;
|
||||
testpath_ = nullptr;
|
||||
err_ = -1;
|
||||
InitProto2StrVector();
|
||||
SetPath(const_cast<char*>("/proc"));
|
||||
}
|
||||
|
||||
MemoryDataPlugin::~MemoryDataPlugin()
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "plugin:~MemoryDataPlugin!");
|
||||
if (buffer_ != nullptr) {
|
||||
free(buffer_);
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
if (meminfoFd_ > 0) {
|
||||
close(meminfoFd_);
|
||||
meminfoFd_ = -1;
|
||||
}
|
||||
if (vmstatFd_ > 0) {
|
||||
close(vmstatFd_);
|
||||
vmstatFd_ = -1;
|
||||
}
|
||||
for (auto it = pidFds_.begin(); it != pidFds_.end(); it++) {
|
||||
for (int i = FILE_STATUS; i <= FILE_SMAPS; i++) {
|
||||
if (it->second[i] != -1) {
|
||||
close(it->second[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::InitProto2StrVector()
|
||||
{
|
||||
int maxprotobufid = 0;
|
||||
for (unsigned int i = 0; i < sizeof(meminfoMapping) / sizeof(meminfoMapping[0]); i++) {
|
||||
maxprotobufid = std::max(meminfoMapping[i].protobufid, maxprotobufid);
|
||||
}
|
||||
meminfoStrList_.resize(maxprotobufid + 1);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(meminfoMapping) / sizeof(meminfoMapping[0]); i++) {
|
||||
meminfoStrList_[meminfoMapping[i].protobufid] = meminfoMapping[i].procstr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int MemoryDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
|
||||
{
|
||||
buffer_ = malloc(READ_BUFFER_SIZE);
|
||||
if (buffer_ == nullptr) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:malloc buffer_ fail");
|
||||
return RET_FAIL;
|
||||
}
|
||||
|
||||
if (protoConfig_.ParseFromArray(configData, configSize) <= 0) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:ParseFromArray failed");
|
||||
return RET_FAIL;
|
||||
}
|
||||
|
||||
if (protoConfig_.report_sysmem_mem_info()) {
|
||||
char fileName[PATH_MAX + 1] = {0};
|
||||
char realPath[PATH_MAX + 1] = {0};
|
||||
if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s/meminfo", testpath_) < 0) {
|
||||
HILOG_ERROR(LOG_CORE, "snprintf_s error");
|
||||
}
|
||||
if (realpath(fileName, realPath) == nullptr) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:realpath failed, errno=%d", errno);
|
||||
return RET_FAIL;
|
||||
}
|
||||
meminfoFd_ = open(realPath, O_RDONLY | O_CLOEXEC);
|
||||
if (meminfoFd_ == -1) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:open failed, fileName, errno=%d", errno);
|
||||
return RET_FAIL;
|
||||
}
|
||||
}
|
||||
if (protoConfig_.report_sysmem_vmem_info()) {
|
||||
vmstatFd_ = open("/proc/vmstat", O_RDONLY | O_CLOEXEC);
|
||||
if (vmstatFd_ == -1) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:Failed to open(/proc/vmstat), errno=%d", errno);
|
||||
return RET_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (protoConfig_.sys_meminfo_counters().size() > 0) {
|
||||
for (int i = 0; i < protoConfig_.sys_meminfo_counters().size(); i++) {
|
||||
if (meminfoStrList_[protoConfig_.sys_meminfo_counters(i)]) {
|
||||
meminfoCounters_.emplace(meminfoStrList_[protoConfig_.sys_meminfo_counters(i)],
|
||||
protoConfig_.sys_meminfo_counters(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (protoConfig_.pid().size() > 0) {
|
||||
for (int i = 0; i < protoConfig_.pid().size(); i++) {
|
||||
int32_t pid = protoConfig_.pid(i);
|
||||
pidFds_.emplace(pid, OpenProcPidFiles(pid));
|
||||
}
|
||||
}
|
||||
|
||||
HILOG_INFO(LOG_CORE, "plugin:start success!");
|
||||
return RET_SUCC;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteMeminfo(MemoryData& data)
|
||||
{
|
||||
int readsize = ReadFile(meminfoFd_);
|
||||
if (readsize == RET_FAIL) {
|
||||
HILOG_ERROR(LOG_CORE, "%s:read meminfoFd fail!", __func__);
|
||||
return;
|
||||
}
|
||||
BufferSplitter totalbuffer((const char*)buffer_, readsize);
|
||||
|
||||
do {
|
||||
if (!totalbuffer.NextWord(':')) {
|
||||
continue;
|
||||
}
|
||||
const_cast<char *>(totalbuffer.CurWord())[totalbuffer.CurWordSize()] = '\0';
|
||||
auto it = meminfoCounters_.find(totalbuffer.CurWord());
|
||||
if (it == meminfoCounters_.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int counter_id = it->second;
|
||||
if (!totalbuffer.NextWord(' ')) {
|
||||
continue;
|
||||
}
|
||||
auto value = static_cast<uint64_t>(strtoll(totalbuffer.CurWord(), nullptr, DEC_BASE));
|
||||
auto* meminfo = data.add_meminfo();
|
||||
|
||||
meminfo->set_key(static_cast<SysMeminfoType>(counter_id));
|
||||
meminfo->set_value(value);
|
||||
} while (totalbuffer.NextLine());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteVmstat(MemoryData& data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteAppsummary(ProcessMemoryInfo* processinfo, SmapsStats& smapInfo)
|
||||
{
|
||||
processinfo->mutable_memsummary()->set_java_heap(smapInfo.GetProcessJavaHeap());
|
||||
processinfo->mutable_memsummary()->set_native_heap(smapInfo.GetProcessNativeHeap());
|
||||
processinfo->mutable_memsummary()->set_code(smapInfo.GetProcessCode());
|
||||
processinfo->mutable_memsummary()->set_stack(smapInfo.GetProcessStack());
|
||||
processinfo->mutable_memsummary()->set_graphics(smapInfo.GetProcessGraphics());
|
||||
processinfo->mutable_memsummary()->set_private_other(smapInfo.GetProcessPrivateOther());
|
||||
processinfo->mutable_memsummary()->set_system(smapInfo.GetProcessSystem());
|
||||
}
|
||||
|
||||
int MemoryDataPlugin::ParseNumber(std::string line)
|
||||
{
|
||||
return atoi(line.substr(line.find_first_of("01234567890")).c_str());
|
||||
}
|
||||
|
||||
bool MemoryDataPlugin::ParseMemInfo(const char* data, ProcessMemoryInfo* memoryInfo)
|
||||
{
|
||||
bool ready = false;
|
||||
bool done = false;
|
||||
std::istringstream ss(data);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(ss, line)) {
|
||||
HILOG_INFO(LOG_CORE, "line: %s", line.c_str());
|
||||
std::string s(line);
|
||||
if (s.find("App Summary") != s.npos) {
|
||||
HILOG_INFO(LOG_CORE, "ready");
|
||||
ready = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ready) {
|
||||
if (s.find("Java Heap:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_java_heap(ParseNumber(s));
|
||||
continue;
|
||||
}
|
||||
if (s.find("Native Heap:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_native_heap(ParseNumber(s));
|
||||
continue;
|
||||
}
|
||||
if (s.find("Code:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_code(ParseNumber(s));
|
||||
continue;
|
||||
}
|
||||
if (s.find("Stack:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_stack(ParseNumber(s));
|
||||
continue;
|
||||
}
|
||||
if (s.find("Graphics:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_graphics(ParseNumber(s));
|
||||
continue;
|
||||
}
|
||||
if (s.find("Private Other:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_private_other(ParseNumber(s));
|
||||
continue;
|
||||
}
|
||||
if (s.find("System:") != s.npos) {
|
||||
memoryInfo->mutable_memsummary()->set_system(ParseNumber(s));
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
bool MemoryDataPlugin::GetMemInfoByDumpsys(uint32_t pid, ProcessMemoryInfo* memoryInfo)
|
||||
{
|
||||
std::string fullCmd = CMD_FORMAT + std::to_string(pid);
|
||||
HILOG_INFO(LOG_CORE, "popen cmd = %s", fullCmd.c_str());
|
||||
|
||||
std::unique_ptr<uint8_t[]> buffer {new (std::nothrow) uint8_t[BUF_MAX_LEN]};
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> fp(popen(fullCmd.c_str(), "r"), pclose);
|
||||
if (!fp) {
|
||||
HILOG_INFO(LOG_CORE, "popen error");
|
||||
return false;
|
||||
}
|
||||
HILOG_INFO(LOG_CORE, "popen ok");
|
||||
|
||||
fread(buffer.get(), 1, BUF_MAX_LEN, fp.get());
|
||||
buffer.get()[BUF_MAX_LEN - 1] = '\0';
|
||||
|
||||
return ParseMemInfo(reinterpret_cast<char*>(buffer.get()), memoryInfo);
|
||||
}
|
||||
|
||||
int MemoryDataPlugin::Report(uint8_t* data, uint32_t dataSize)
|
||||
{
|
||||
MemoryData dataProto;
|
||||
uint32_t length;
|
||||
|
||||
if (protoConfig_.report_process_tree()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:report process list");
|
||||
WriteProcesseList(dataProto);
|
||||
}
|
||||
|
||||
if (protoConfig_.report_sysmem_mem_info()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:report system mem_info list");
|
||||
WriteMeminfo(dataProto);
|
||||
}
|
||||
|
||||
if (protoConfig_.report_sysmem_vmem_info()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:report system vmem_info list");
|
||||
WriteVmstat(dataProto);
|
||||
}
|
||||
|
||||
if (protoConfig_.pid().size() > 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:set pid counter, cnt = %d", protoConfig_.pid().size());
|
||||
|
||||
for (int i = 0; i < protoConfig_.pid().size(); i++) {
|
||||
int32_t pid = protoConfig_.pid(i);
|
||||
|
||||
auto* processinfo = dataProto.add_processesinfo();
|
||||
if (protoConfig_.report_process_mem_info()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:need report meminfo pid(%d)", pid);
|
||||
WriteProcinfoByPidfds(processinfo, pid);
|
||||
}
|
||||
|
||||
if (protoConfig_.report_app_mem_info()) {
|
||||
if (protoConfig_.report_app_mem_by_dumpsys()) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:report_app_mem_by_dumpsys");
|
||||
GetMemInfoByDumpsys(pid, processinfo);
|
||||
} else {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:need report appmeminfo pid(%d)", pid);
|
||||
SmapsStats smapInfo;
|
||||
smapInfo.ParseMaps(pid);
|
||||
WriteAppsummary(processinfo, smapInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
length = dataProto.ByteSizeLong();
|
||||
if (length > dataSize) {
|
||||
return -length;
|
||||
}
|
||||
if (dataProto.SerializeToArray(data, length) > 0) {
|
||||
HILOG_DEBUG(LOG_CORE, "plugin:report success! length = %d", length);
|
||||
return length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MemoryDataPlugin::Stop()
|
||||
{
|
||||
if (buffer_ != nullptr) {
|
||||
free(buffer_);
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
if (meminfoFd_ > 0) {
|
||||
close(meminfoFd_);
|
||||
meminfoFd_ = -1;
|
||||
}
|
||||
if (vmstatFd_ > 0) {
|
||||
close(vmstatFd_);
|
||||
vmstatFd_ = -1;
|
||||
}
|
||||
for (auto it = pidFds_.begin(); it != pidFds_.end(); it++) {
|
||||
for (int i = FILE_STATUS; i <= FILE_SMAPS; i++) {
|
||||
if (it->second[i] != -1) {
|
||||
close(it->second[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
HILOG_INFO(LOG_CORE, "plugin:stop success!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteProcinfoByPidfds(ProcessMemoryInfo* processinfo, int32_t pid)
|
||||
{
|
||||
char* end = nullptr;
|
||||
int32_t readSize;
|
||||
|
||||
readSize = ReadFile(pidFds_[pid][FILE_STATUS]);
|
||||
if (readSize != RET_FAIL) {
|
||||
WriteProcess(processinfo, (char*)buffer_, readSize, pid);
|
||||
} else {
|
||||
SetEmptyProcessInfo(processinfo);
|
||||
}
|
||||
if (ReadFile(pidFds_[pid][FILE_OOM]) != RET_FAIL) {
|
||||
processinfo->set_oom_score_adj(strtol((char*)buffer_, &end, DEC_BASE));
|
||||
} else {
|
||||
processinfo->set_oom_score_adj(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t MemoryDataPlugin::ReadFile(int fd)
|
||||
{
|
||||
if ((buffer_ == nullptr) || (fd == -1)) {
|
||||
HILOG_ERROR(LOG_CORE, "%s:Empty address, or invalid fd", __func__);
|
||||
return RET_FAIL;
|
||||
}
|
||||
int readsize = pread(fd, buffer_, READ_BUFFER_SIZE - 1, 0);
|
||||
if (readsize <= 0) {
|
||||
HILOG_ERROR(LOG_CORE, "Failed to read(%d), errno=%d", fd, errno);
|
||||
err_ = errno;
|
||||
return RET_FAIL;
|
||||
}
|
||||
return readsize;
|
||||
}
|
||||
|
||||
std::vector<int> MemoryDataPlugin::OpenProcPidFiles(int32_t pid)
|
||||
{
|
||||
int fd = -1;
|
||||
char fileName[PATH_MAX + 1] = {0};
|
||||
char realPath[PATH_MAX + 1] = {0};
|
||||
int count = sizeof(procfdMapping) / sizeof(procfdMapping[0]);
|
||||
std::vector<int> profds;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1,
|
||||
"%s/%d/%s", testpath_, pid, procfdMapping[i].file) < 0) {
|
||||
HILOG_ERROR(LOG_CORE, "snprintf_s error");
|
||||
}
|
||||
if (realpath(fileName, realPath) == nullptr) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:realpath failed, errno=%d", errno);
|
||||
}
|
||||
fd = open(realPath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
HILOG_ERROR(LOG_CORE, "Failed to open(%s), errno=%d", fileName, errno);
|
||||
}
|
||||
profds.emplace(profds.begin() + i, fd);
|
||||
}
|
||||
return profds;
|
||||
}
|
||||
|
||||
DIR* MemoryDataPlugin::OpenDestDir(const char* dirPath)
|
||||
{
|
||||
DIR* destDir = nullptr;
|
||||
|
||||
destDir = opendir(dirPath);
|
||||
if (destDir == nullptr) {
|
||||
HILOG_ERROR(LOG_CORE, "Failed to opendir(%s), errno=%d", dirPath, errno);
|
||||
}
|
||||
|
||||
return destDir;
|
||||
}
|
||||
|
||||
int32_t MemoryDataPlugin::GetValidPid(DIR* dirp)
|
||||
{
|
||||
if (!dirp) return 0;
|
||||
while (struct dirent* dirEnt = readdir(dirp)) {
|
||||
if (dirEnt->d_type != DT_DIR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t pid = atoi(dirEnt->d_name);
|
||||
if (pid) {
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t MemoryDataPlugin::ReadProcPidFile(int32_t pid, const char* pFileName)
|
||||
{
|
||||
char fileName[PATH_MAX + 1] = {0};
|
||||
char realPath[PATH_MAX + 1] = {0};
|
||||
int fd = -1;
|
||||
ssize_t bytesRead;
|
||||
|
||||
if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s/%d/%s", testpath_, pid, pFileName) < 0) {
|
||||
HILOG_ERROR(LOG_CORE, "snprintf_s error");
|
||||
}
|
||||
if (realpath(fileName, realPath) == nullptr) {
|
||||
HILOG_ERROR(LOG_CORE, "plugin:realpath failed, errno=%d", errno);
|
||||
return RET_FAIL;
|
||||
}
|
||||
fd = open(realPath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
HILOG_INFO(LOG_CORE, "Failed to open(%s), errno=%d", fileName, errno);
|
||||
err_ = errno;
|
||||
return RET_FAIL;
|
||||
}
|
||||
if (buffer_ == nullptr) {
|
||||
HILOG_INFO(LOG_CORE, "%s:Empty address, buffer_ is NULL", __func__);
|
||||
err_ = RET_NULL_ADDR;
|
||||
close(fd);
|
||||
return RET_FAIL;
|
||||
}
|
||||
bytesRead = read(fd, buffer_, READ_BUFFER_SIZE - 1);
|
||||
if (bytesRead <= 0) {
|
||||
close(fd);
|
||||
HILOG_INFO(LOG_CORE, "Failed to read(%s), errno=%d", fileName, errno);
|
||||
err_ = errno;
|
||||
return RET_FAIL;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
bool MemoryDataPlugin::BufnCmp(const char* src, int srcLen, const char* key, int keyLen)
|
||||
{
|
||||
if (!src || !key || (srcLen < keyLen)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < keyLen; i++) {
|
||||
if (*src++ != *key++) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryDataPlugin::addPidBySort(int32_t pid)
|
||||
{
|
||||
auto pidsEnd = seenPids_.end();
|
||||
auto it = std::lower_bound(seenPids_.begin(), pidsEnd, pid);
|
||||
if (it != pidsEnd && *it == pid) {
|
||||
return false;
|
||||
}
|
||||
it = seenPids_.insert(it, std::move(pid));
|
||||
return true;
|
||||
}
|
||||
|
||||
int MemoryDataPlugin::GetProcStatusId(const char* src, int srcLen)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = sizeof(procStatusMapping) / sizeof(procStatusMapping[0]);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (BufnCmp(src, srcLen, procStatusMapping[i].procstr, strlen(procStatusMapping[i].procstr))) {
|
||||
return procStatusMapping[i].procid;
|
||||
}
|
||||
}
|
||||
return RET_FAIL;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::SetProcessInfo(ProcessMemoryInfo* processinfo, int key, const char* word)
|
||||
{
|
||||
char* end = nullptr;
|
||||
|
||||
switch (key) {
|
||||
case PRO_TGID: {
|
||||
processinfo->set_pid(strtoul(word, &end, DEC_BASE));
|
||||
} break;
|
||||
case PRO_VMSIZE: {
|
||||
uint64_t vm_size_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_vm_size_kb(vm_size_kb);
|
||||
} break;
|
||||
case PRO_VMRSS: {
|
||||
uint64_t vm_rss_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_vm_rss_kb(vm_rss_kb);
|
||||
} break;
|
||||
case PRO_RSSANON: {
|
||||
uint64_t rss_anon_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_rss_anon_kb(rss_anon_kb);
|
||||
} break;
|
||||
case PRO_RSSFILE: {
|
||||
uint64_t rss_file_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_rss_file_kb(rss_file_kb);
|
||||
} break;
|
||||
case PRO_RSSSHMEM: {
|
||||
uint64_t rss_shmem_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_rss_shmem_kb(rss_shmem_kb);
|
||||
} break;
|
||||
case PRO_VMSWAP: {
|
||||
uint64_t vm_swap_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_vm_swap_kb(vm_swap_kb);
|
||||
} break;
|
||||
case PRO_VMLCK: {
|
||||
uint64_t vm_locked_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_vm_locked_kb(vm_locked_kb);
|
||||
} break;
|
||||
case PRO_VMHWM: {
|
||||
uint64_t vm_hwm_kb = strtoul(word, &end, DEC_BASE);
|
||||
processinfo->set_vm_hwm_kb(vm_hwm_kb);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteProcess(ProcessMemoryInfo* processinfo, const char* pFile, uint32_t fileLen, int32_t pid)
|
||||
{
|
||||
BufferSplitter totalbuffer(const_cast<const char*>(pFile), fileLen + 1);
|
||||
|
||||
do {
|
||||
totalbuffer.NextWord(':');
|
||||
if (!totalbuffer.CurWord()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int key = GetProcStatusId(totalbuffer.CurWord(), totalbuffer.CurWordSize());
|
||||
totalbuffer.NextWord('\n');
|
||||
if (!totalbuffer.CurWord()) {
|
||||
continue;
|
||||
}
|
||||
if (key == PRO_NAME) {
|
||||
processinfo->set_name(totalbuffer.CurWord(), totalbuffer.CurWordSize());
|
||||
}
|
||||
SetProcessInfo(processinfo, key, totalbuffer.CurWord());
|
||||
} while (totalbuffer.NextLine());
|
||||
// update process name
|
||||
int32_t ret = ReadProcPidFile(pid, "cmdline");
|
||||
if (ret > 0) {
|
||||
processinfo->set_name(static_cast<char*>(buffer_), strlen(static_cast<char*>(buffer_)));
|
||||
HILOG_ERROR(LOG_CORE, "%s:update process name=%s", __func__, processinfo->name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::SetEmptyProcessInfo(ProcessMemoryInfo* processinfo)
|
||||
{
|
||||
processinfo->set_pid(-1);
|
||||
processinfo->set_name("null");
|
||||
processinfo->set_vm_size_kb(0);
|
||||
processinfo->set_vm_rss_kb(0);
|
||||
processinfo->set_rss_anon_kb(0);
|
||||
processinfo->set_rss_file_kb(0);
|
||||
processinfo->set_rss_shmem_kb(0);
|
||||
processinfo->set_vm_swap_kb(0);
|
||||
processinfo->set_vm_locked_kb(0);
|
||||
processinfo->set_vm_hwm_kb(0);
|
||||
processinfo->set_oom_score_adj(0);
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteOomInfo(ProcessMemoryInfo* processinfo, int32_t pid)
|
||||
{
|
||||
char* end = nullptr;
|
||||
|
||||
if (ReadProcPidFile(pid, "oom_score_adj") == RET_FAIL) {
|
||||
processinfo->set_oom_score_adj(0);
|
||||
return;
|
||||
}
|
||||
if (buffer_ == nullptr) {
|
||||
processinfo->set_oom_score_adj(0);
|
||||
HILOG_ERROR(LOG_CORE, "%s:invalid params, read buffer_ is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
processinfo->set_oom_score_adj(strtol((char*)buffer_, &end, DEC_BASE));
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteProcessInfo(MemoryData& data, int32_t pid)
|
||||
{
|
||||
int32_t ret = ReadProcPidFile(pid, "status");
|
||||
if (ret == RET_FAIL) {
|
||||
SetEmptyProcessInfo(data.add_processesinfo());
|
||||
return;
|
||||
}
|
||||
if ((buffer_ == nullptr) || (ret == 0)) {
|
||||
HILOG_ERROR(LOG_CORE, "%s:invalid params, read buffer_ is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
auto* processinfo = data.add_processesinfo();
|
||||
WriteProcess(processinfo, (char*)buffer_, ret, pid);
|
||||
WriteOomInfo(processinfo, pid);
|
||||
}
|
||||
|
||||
void MemoryDataPlugin::WriteProcesseList(MemoryData& data)
|
||||
{
|
||||
DIR* procDir = nullptr;
|
||||
|
||||
procDir = OpenDestDir(testpath_);
|
||||
if (procDir == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (int32_t pid = GetValidPid(procDir)) {
|
||||
if (find(seenPids_.begin(), seenPids_.end(), pid) == seenPids_.end()) {
|
||||
addPidBySort(pid);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < seenPids_.size(); i++) {
|
||||
WriteProcessInfo(data, seenPids_[i]);
|
||||
}
|
||||
closedir(procDir);
|
||||
}
|
61
device/plugins/memory_plugin/src/memory_module.cpp
Executable file
61
device/plugins/memory_plugin/src/memory_module.cpp
Executable file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "memory_data_plugin.h"
|
||||
#include <mutex>
|
||||
#include <sys/types.h>
|
||||
#include "plugin_module_api.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
|
||||
std::unique_ptr<MemoryDataPlugin> g_plugin = nullptr;
|
||||
std::mutex g_taskMutex;
|
||||
} // namespace
|
||||
|
||||
static int MemDataPluginSessionStart(const uint8_t* configData, uint32_t configSize)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_taskMutex);
|
||||
g_plugin = std::make_unique<MemoryDataPlugin>();
|
||||
return g_plugin->Start(configData, configSize);
|
||||
}
|
||||
|
||||
static int MemPluginReportResult(uint8_t* bufferData, uint32_t bufferSize)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_taskMutex);
|
||||
return g_plugin->Report(bufferData, bufferSize);
|
||||
}
|
||||
|
||||
static int MemPluginSessionStop()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_taskMutex);
|
||||
HILOG_INFO(LOG_CORE, "%s:stop Session success!", __func__);
|
||||
g_plugin->Stop();
|
||||
g_plugin = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int MemRegisterWriterStruct(const WriterStruct* writer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PluginModuleCallbacks g_callbacks = {
|
||||
MemDataPluginSessionStart,
|
||||
MemPluginReportResult,
|
||||
MemPluginSessionStop,
|
||||
MemRegisterWriterStruct,
|
||||
};
|
||||
|
||||
PluginModuleStruct g_pluginModule = {&g_callbacks, "memory-plugin", MAX_BUFFER_SIZE};
|
422
device/plugins/memory_plugin/src/smaps_stats.cpp
Executable file
422
device/plugins/memory_plugin/src/smaps_stats.cpp
Executable file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "smaps_stats.h"
|
||||
|
||||
#include "securec.h"
|
||||
|
||||
namespace {
|
||||
bool MatchHead(const std::string& name, const char* str)
|
||||
{
|
||||
return strncmp(name.c_str(), str, strlen(str)) == 0;
|
||||
}
|
||||
|
||||
bool MatchTail(const std::string& name, std::string str)
|
||||
{
|
||||
int index = name.size() - str.size();
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
return (name.substr(index) == str);
|
||||
}
|
||||
} // namespace
|
||||
bool SmapsStats::ParseMaps(int pid)
|
||||
{
|
||||
std::string smaps_path = std::string("/proc/") + std::to_string(pid) + std::string("/smaps");
|
||||
if (testpath_.size() > 0) {
|
||||
smaps_path = testpath_ + std::to_string(pid) + std::string("/smaps");
|
||||
}
|
||||
HILOG_INFO(LOG_CORE, "smaps path:%s", smaps_path.c_str());
|
||||
ReadVmemareasFile(smaps_path);
|
||||
ReviseStatsData();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmapsStats::ReadVmemareasFile(const std::string& path)
|
||||
{
|
||||
bool findMapHead = false;
|
||||
MapPiecesInfo_t mappic = {0};
|
||||
MemUsageInfo_t memusage = {0};
|
||||
uint64_t prevEnd = 0;
|
||||
int prevHeap = 0;
|
||||
std::ifstream input(path, std::ios::in);
|
||||
if (input.fail()) {
|
||||
HILOG_ERROR(LOG_CORE, "open %s failed, errno = %d", path.c_str(), errno);
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
if (!input.good()) {
|
||||
return false;
|
||||
}
|
||||
std::string line;
|
||||
getline(input, line);
|
||||
line += '\n';
|
||||
if (!findMapHead) {
|
||||
// 00400000-00409000 r-xp 00000000 fc:00 426998 /usr/lib/gvfs/gvfsd-http
|
||||
ParseMapHead(line, mappic);
|
||||
findMapHead = true;
|
||||
continue;
|
||||
}
|
||||
if (findMapHead && GetMemUsageField(line, memusage)) {
|
||||
if (!lastline_) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
CollectVmemAreasData(mappic, memusage, prevEnd, prevHeap);
|
||||
findMapHead = false;
|
||||
lastline_ = false;
|
||||
} while (!input.eof());
|
||||
input.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmapsStats::GetVMAStuId(int ops,
|
||||
std::string name,
|
||||
const vMeminfoAreaMapping* vma,
|
||||
int count,
|
||||
int32_t heapIndex[2],
|
||||
bool& swappable)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (ops == OPS_START) {
|
||||
if (MatchHead(name, vma[i].heapstr)) {
|
||||
heapIndex[0] = vma[i].heapid[0];
|
||||
heapIndex[1] = vma[i].heapid[1];
|
||||
swappable = false;
|
||||
return true;
|
||||
}
|
||||
} else if (ops == OPS_END) {
|
||||
if (MatchTail(name, vma[i].heapstr)) {
|
||||
if (vma[i].heapid[1] == VMHEAP_NEEDFIX) {
|
||||
HeapIndexFix(name, vma[i].heapstr, heapIndex);
|
||||
} else {
|
||||
heapIndex[0] = vma[i].heapid[0];
|
||||
heapIndex[1] = vma[i].heapid[1];
|
||||
}
|
||||
swappable = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SmapsStats::GetVmaIndex(std::string name, uint32_t namesz, int32_t heapIndex[2], bool& swappable)
|
||||
{
|
||||
switch (name[0]) {
|
||||
case '[':
|
||||
if (MatchHead(name, "[heap]") || MatchHead(name, "[stack")) {
|
||||
int count = sizeof(vmaMemheap) / sizeof(vmaMemheap[0]);
|
||||
return GetVMAStuId(OPS_START, name, vmaMemheap, count, heapIndex, swappable);
|
||||
} else if (MatchHead(name, "[anon:")) {
|
||||
if (MatchHead(name, "[anon:dalvik-")) {
|
||||
int count = sizeof(vmaMemsuffix) / sizeof(vmaMemsuffix[0]);
|
||||
if (GetVMAStuId(OPS_END, name, vmaMemsuffix, count, heapIndex, swappable)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
int count = sizeof(vmaMemanon) / sizeof(vmaMemanon[0]);
|
||||
return GetVMAStuId(OPS_START, name, vmaMemanon, count, heapIndex, swappable);
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
if (MatchHead(name, "/memfd:")) {
|
||||
int count = sizeof(vmaMemfd) / sizeof(vmaMemfd[0]);
|
||||
return GetVMAStuId(OPS_START, name, vmaMemfd, count, heapIndex, swappable);
|
||||
} else if (MatchHead(name, "/dev/")) {
|
||||
int count = sizeof(vmaMemdev) / sizeof(vmaMemdev[0]);
|
||||
return GetVMAStuId(OPS_START, name, vmaMemdev, count, heapIndex, swappable);
|
||||
} else {
|
||||
int count = sizeof(vmaMemsuffix) / sizeof(vmaMemsuffix[0]);
|
||||
return GetVMAStuId(OPS_END, name, vmaMemsuffix, count, heapIndex, swappable);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
int count = sizeof(vmaMemsuffix) / sizeof(vmaMemsuffix[0]);
|
||||
return GetVMAStuId(OPS_END, name, vmaMemsuffix, count, heapIndex, swappable);
|
||||
break;
|
||||
}
|
||||
if (namesz > strlen(".dex") && strstr(name.c_str(), ".dex") != nullptr) {
|
||||
heapIndex[0] = VMHEAP_DEX;
|
||||
heapIndex[1] = VMHEAP_DEX_APP_DEX;
|
||||
swappable = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SmapsStats::CollectVmemAreasData(const MapPiecesInfo_t& mempic,
|
||||
const MemUsageInfo_t& memusage,
|
||||
uint64_t& prevEnd,
|
||||
int& prevHeap)
|
||||
{
|
||||
std::string name;
|
||||
int32_t heapIndex[2] = {VMHEAP_UNKNOWN, VMHEAP_NULL};
|
||||
bool swappable = false;
|
||||
uint64_t swapablePss = 0;
|
||||
|
||||
if (MatchTail(mempic.name, " (deleted)")) {
|
||||
name = mempic.name.substr(0, mempic.name.size() - strlen(" (deleted)"));
|
||||
} else {
|
||||
name = mempic.name;
|
||||
}
|
||||
uint32_t namesz = name.size();
|
||||
if (!GetVmaIndex(name, namesz, heapIndex, swappable)) {
|
||||
if (namesz > 0) {
|
||||
heapIndex[0] = VMHEAP_UNKNOWN_MAP;
|
||||
} else if (mempic.start_addr == prevEnd && prevHeap == VMHEAP_SO) {
|
||||
// bss section of a shared library
|
||||
heapIndex[0] = VMHEAP_SO;
|
||||
}
|
||||
}
|
||||
prevEnd = mempic.end_addr;
|
||||
prevHeap = heapIndex[0];
|
||||
swapablePss = GetSwapablepssValue(memusage, swappable);
|
||||
SetVmemAreasData(heapIndex[0], swapablePss, memusage);
|
||||
if ((heapIndex[1] != VMHEAP_NULL) && (heapIndex[1] != VMHEAP_NEEDFIX)) {
|
||||
SetVmemAreasData(heapIndex[1], swapablePss, memusage);
|
||||
}
|
||||
}
|
||||
|
||||
void SmapsStats::ReviseStatsData()
|
||||
{
|
||||
// Summary data to VMHEAP_UNKNOWN
|
||||
for (int i = _NUM_CORE_HEAP; i < _NUM_EXCLUSIVE_HEAP; i++) {
|
||||
stats_[VMHEAP_UNKNOWN].pss += stats_[i].pss;
|
||||
stats_[VMHEAP_UNKNOWN].swappablePss += stats_[i].swappablePss;
|
||||
stats_[VMHEAP_UNKNOWN].rss += stats_[i].rss;
|
||||
stats_[VMHEAP_UNKNOWN].privateDirty += stats_[i].privateDirty;
|
||||
stats_[VMHEAP_UNKNOWN].sharedDirty += stats_[i].sharedDirty;
|
||||
stats_[VMHEAP_UNKNOWN].privateClean += stats_[i].privateClean;
|
||||
stats_[VMHEAP_UNKNOWN].sharedClean += stats_[i].sharedClean;
|
||||
stats_[VMHEAP_UNKNOWN].swappedOut += stats_[i].swappedOut;
|
||||
stats_[VMHEAP_UNKNOWN].swappedOutPss += stats_[i].swappedOutPss;
|
||||
}
|
||||
}
|
||||
|
||||
bool SmapsStats::SetMapAddrInfo(std::string& line, MapPiecesInfo_t& head)
|
||||
{
|
||||
const char* pStr = line.c_str();
|
||||
char* end = nullptr;
|
||||
// start_addr
|
||||
head.start_addr = strtoull(pStr, &end, HEX_BASE);
|
||||
if (end == pStr || *end != '-') {
|
||||
return false;
|
||||
}
|
||||
pStr = end + 1;
|
||||
// end_addr
|
||||
head.end_addr = strtoull(pStr, &end, HEX_BASE);
|
||||
if (end == pStr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmapsStats::ParseMapHead(std::string& line, MapPiecesInfo_t& head)
|
||||
{
|
||||
if (!SetMapAddrInfo(line, head)) {
|
||||
return false;
|
||||
}
|
||||
size_t newlineops = 0;
|
||||
size_t wordsz = 0;
|
||||
std::string newline = line;
|
||||
for (int i = 0; i < FIFTH_FIELD; i++) {
|
||||
std::string word = newline;
|
||||
wordsz = word.find(" ");
|
||||
if (wordsz == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
word = newline.substr(0, wordsz);
|
||||
|
||||
newlineops = newline.find_first_not_of(" ", wordsz);
|
||||
newline = newline.substr(newlineops);
|
||||
}
|
||||
head.name = newline.substr(0, newline.size() - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmapsStats::GetMemUsageField(std::string& line, MemUsageInfo_t& memusage)
|
||||
{
|
||||
char field[64];
|
||||
int len;
|
||||
const char* pLine = line.c_str();
|
||||
|
||||
int ret = sscanf_s(pLine, "%63s %n", field, sizeof(field), &len);
|
||||
if (ret == 1 && *field && field[strlen(field) - 1] == ':') {
|
||||
const char* c = pLine + len;
|
||||
std::string strfield(field);
|
||||
switch (field[0]) {
|
||||
case 'P':
|
||||
if (MatchHead(strfield, "Pss:")) {
|
||||
memusage.pss = strtoull(c, nullptr, DEC_BASE);
|
||||
} else if (MatchHead(strfield, "Private_Clean:")) {
|
||||
uint64_t prcl = strtoull(c, nullptr, DEC_BASE);
|
||||
memusage.private_clean = prcl;
|
||||
memusage.uss += prcl;
|
||||
} else if (MatchHead(strfield, "Private_Dirty:")) {
|
||||
uint64_t prdi = strtoull(c, nullptr, DEC_BASE);
|
||||
memusage.private_dirty = prdi;
|
||||
memusage.uss += prdi;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
if (MatchHead(strfield, "Size:")) {
|
||||
memusage.vss = strtoull(c, nullptr, DEC_BASE);
|
||||
} else if (MatchHead(strfield, "Shared_Clean:")) {
|
||||
memusage.shared_clean = strtoull(c, nullptr, DEC_BASE);
|
||||
} else if (MatchHead(strfield, "Shared_Dirty:")) {
|
||||
memusage.shared_dirty = strtoull(c, nullptr, DEC_BASE);
|
||||
} else if (MatchHead(strfield, "Swap:")) {
|
||||
memusage.swap = strtoull(c, nullptr, DEC_BASE);
|
||||
} else if (MatchHead(strfield, "SwapPss:")) {
|
||||
memusage.swap_pss = strtoull(c, nullptr, DEC_BASE);
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
if (MatchHead(strfield, "Rss:")) {
|
||||
memusage.rss = strtoull(c, nullptr, DEC_BASE);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
if (MatchHead(strfield, "VmFlags:")) {
|
||||
lastline_ = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t SmapsStats::GetSwapablepssValue(const MemUsageInfo_t& memusage, bool swappable)
|
||||
{
|
||||
const MemUsageInfo_t& usage = memusage;
|
||||
uint64_t swapablePss = 0;
|
||||
|
||||
if (swappable && (usage.pss > 0)) {
|
||||
float sharing_proportion = 0.0f;
|
||||
if ((usage.shared_clean > 0) || (usage.shared_dirty > 0)) {
|
||||
sharing_proportion = (usage.pss - usage.uss) / (usage.shared_clean + usage.shared_dirty);
|
||||
}
|
||||
swapablePss = (sharing_proportion * usage.shared_clean) + usage.private_clean;
|
||||
}
|
||||
return swapablePss;
|
||||
}
|
||||
|
||||
void SmapsStats::SetVmemAreasData(int index, uint64_t swapablePss, const MemUsageInfo_t& usage)
|
||||
{
|
||||
stats_[index].pss += usage.pss;
|
||||
stats_[index].swappablePss += swapablePss;
|
||||
stats_[index].rss += usage.rss;
|
||||
stats_[index].privateDirty += usage.private_dirty;
|
||||
stats_[index].sharedDirty += usage.shared_dirty;
|
||||
stats_[index].privateClean += usage.private_clean;
|
||||
stats_[index].sharedClean += usage.shared_clean;
|
||||
stats_[index].swappedOut += usage.swap;
|
||||
stats_[index].swappedOutPss += usage.swap_pss;
|
||||
}
|
||||
|
||||
void SmapsStats::HeapIndexFix(std::string name, const char* key, int32_t heapIndex[2])
|
||||
{
|
||||
if (!strncmp(key, ".vdex", sizeof(".vdex"))) {
|
||||
if ((strstr(name.c_str(), "@boot") != nullptr) || (strstr(name.c_str(), "/boot") != nullptr) ||
|
||||
(strstr(name.c_str(), "/apex") != nullptr)) {
|
||||
heapIndex[0] = VMHEAP_DEX;
|
||||
heapIndex[1] = VMHEAP_DEX_BOOT_VDEX;
|
||||
} else {
|
||||
heapIndex[0] = VMHEAP_DEX;
|
||||
heapIndex[1] = VMHEAP_DEX_APP_VDEX;
|
||||
}
|
||||
} else if (!strncmp(key, ".art", sizeof(".art")) || !strncmp(key, ".art]", sizeof(".art]"))) {
|
||||
if ((strstr(name.c_str(), "@boot") != nullptr) || (strstr(name.c_str(), "/boot") != nullptr) ||
|
||||
(strstr(name.c_str(), "/apex") != nullptr)) {
|
||||
heapIndex[0] = VMHEAP_ART;
|
||||
heapIndex[1] = VMHEAP_ART_BOOT;
|
||||
} else {
|
||||
heapIndex[0] = VMHEAP_ART;
|
||||
heapIndex[1] = VMHEAP_ART_APP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessJavaHeap()
|
||||
{
|
||||
return stats_[VMHEAP_DALVIK].privateDirty + GetPrivate(VMHEAP_ART);
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessNativeHeap()
|
||||
{
|
||||
return stats_[VMHEAP_NATIVE].privateDirty;
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessCode()
|
||||
{
|
||||
return GetPrivate(VMHEAP_SO) + GetPrivate(VMHEAP_JAR) + GetPrivate(VMHEAP_TTF) +
|
||||
GetPrivate(VMHEAP_DEX) + GetPrivate(VMHEAP_OAT) +
|
||||
GetPrivate(VMHEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE) +
|
||||
GetPrivate(VMHEAP_DALVIK_OTHER_APP_CODE_CACHE);
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessStack()
|
||||
{
|
||||
return stats_[VMHEAP_STACK].privateDirty;
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessGraphics()
|
||||
{
|
||||
return GetPrivate(VMHEAP_GL_DEV) + GetPrivate(VMHEAP_GRAPHICS) + GetPrivate(VMHEAP_GL);
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessPrivateOther()
|
||||
{
|
||||
return GetTotalPrivateClean() + GetTotalPrivateDirty() - GetProcessJavaHeap() - GetProcessNativeHeap() -
|
||||
GetProcessCode() - GetProcessStack() - GetProcessGraphics();
|
||||
}
|
||||
|
||||
int SmapsStats::GetProcessSystem()
|
||||
{
|
||||
return GetTotalPss() - GetTotalPrivateClean() - GetTotalPrivateDirty();
|
||||
}
|
||||
|
||||
int SmapsStats::GetTotalPrivateClean()
|
||||
{
|
||||
return stats_[VMHEAP_UNKNOWN].privateClean + stats_[VMHEAP_NATIVE].privateClean +
|
||||
stats_[VMHEAP_DALVIK].privateClean;
|
||||
}
|
||||
|
||||
int SmapsStats::GetTotalPrivateDirty()
|
||||
{
|
||||
return stats_[VMHEAP_UNKNOWN].privateDirty + stats_[VMHEAP_NATIVE].privateDirty +
|
||||
stats_[VMHEAP_DALVIK].privateDirty;
|
||||
}
|
||||
|
||||
int SmapsStats::GetPrivate(int type)
|
||||
{
|
||||
return stats_[type].privateDirty + stats_[type].privateClean;
|
||||
}
|
||||
|
||||
int SmapsStats::GetTotalPss()
|
||||
{
|
||||
return stats_[VMHEAP_UNKNOWN].pss + stats_[VMHEAP_NATIVE].pss + stats_[VMHEAP_DALVIK].pss + GetTotalSwappedOutPss();
|
||||
}
|
||||
|
||||
int SmapsStats::GetTotalSwappedOutPss()
|
||||
{
|
||||
return stats_[VMHEAP_UNKNOWN].swappedOutPss + stats_[VMHEAP_NATIVE].swappedOutPss +
|
||||
stats_[VMHEAP_DALVIK].swappedOutPss;
|
||||
}
|
60
device/plugins/memory_plugin/test/BUILD.gn
Normal file
60
device/plugins/memory_plugin/test/BUILD.gn
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/test.gni")
|
||||
import("../../../base/config.gni")
|
||||
|
||||
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
|
||||
config("module_private_config") {
|
||||
visibility = [":*"]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
}
|
||||
}
|
||||
|
||||
ohos_unittest("memdataplugin_ut") {
|
||||
module_out_path = module_output_path
|
||||
sources = [
|
||||
"unittest/buffer_splitter_unittest.cpp",
|
||||
"unittest/memory_data_plugin_unittest.cpp",
|
||||
]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_DIR}/device/plugins/memory_plugin:memdataplugin",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/memory_data:memory_data_cpp",
|
||||
"//third_party/googletest:gtest_main",
|
||||
]
|
||||
include_dirs = [
|
||||
"../include",
|
||||
"../../api/include",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
"${OHOS_PROFILER_DIR}/device/base/include",
|
||||
"//third_party/googletest/googletest/include/gtest",
|
||||
]
|
||||
cflags = [
|
||||
"-Wno-inconsistent-missing-override",
|
||||
"-Dprivate=public", #allow test code access private members
|
||||
]
|
||||
external_deps = [
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
]
|
||||
configs = [ ":module_private_config" ]
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
resource_config_file = get_path_info("utresources/ohos_test.xml", "abspath")
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [
|
||||
":memdataplugin_ut",
|
||||
]
|
||||
}
|
@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <memory>
|
||||
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
|
||||
#include "buffer_splitter.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
using ConstCharPtr = std::unique_ptr<const char>::pointer;
|
||||
|
||||
namespace {
|
||||
class BufferSplitterUnittest : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase() {}
|
||||
|
||||
static void TearDownTestCase() {}
|
||||
void SetUp() {}
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
struct TestElement {
|
||||
int32_t index;
|
||||
ConstCharPtr curLine;
|
||||
size_t curLineSz;
|
||||
ConstCharPtr curWord;
|
||||
size_t curWordSz;
|
||||
};
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Constructed function test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, constructorWithNullptr, TestSize.Level1)
|
||||
{
|
||||
char* text = nullptr;
|
||||
int readsize = 0;
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurLine());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurWord());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Constructed function test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, constructorWith1lengthBuffer01, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'\0'};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurLine());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurWord());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Constructed function test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, constructorWith1lengthBuffer02, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'\n'};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurLine());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurWord());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Constructed function test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, constructorWith1lengthBuffer03, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'3'};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurLine());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurWord());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Constructed function test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, constructorWith1LineBuffer, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', 'c', 'd', '\0'};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
TestElement expect = {0, text, 4, nullptr, 0};
|
||||
EXPECT_EQ(expect.curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect.curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(expect.curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect.curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Constructed function test.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, constructorWithMultipleLinesBuffer, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', 'c', 'd', '\n', '1', '2', '3', '4', '5', '\0'};
|
||||
TestElement expect = {0, text, 4, nullptr, 0};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
EXPECT_EQ(expect.curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect.curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(expect.curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect.curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextLine().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextLineWithOnlyOneLineBuffer, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', 'c', 'd', '\0'};
|
||||
TestElement expect = {0, text, 4, nullptr, 0};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
EXPECT_EQ(expect.curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect.curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(expect.curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect.curWordSz, totalbuffer.CurWordSize());
|
||||
|
||||
EXPECT_FALSE(totalbuffer.NextLine());
|
||||
EXPECT_EQ(nullptr, totalbuffer.CurLine());
|
||||
EXPECT_EQ((size_t)0, totalbuffer.CurLineSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextLine().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextLineWithMultipleLinesBuffer, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', 'c', 'd', '\n', '1', '2', '3', '4', '5', '6', '\0'};
|
||||
TestElement expect[] = {{0, text, 4, nullptr, 0}, {5, &text[5], 6, nullptr, 0}};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
size_t i = 0;
|
||||
do {
|
||||
EXPECT_EQ(expect[i].curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect[i].curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_EQ(expect[i].curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect[i].curWordSz, totalbuffer.CurWordSize());
|
||||
i++;
|
||||
} while (totalbuffer.NextLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithOnlyOneLineBuffer01, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', '\0'};
|
||||
TestElement expect = {0, text, 5, text, 2};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
EXPECT_EQ(expect.curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect.curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_TRUE(totalbuffer.NextWord(' '));
|
||||
EXPECT_EQ(expect.curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect.curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithOnlyOneLineBuffer02, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', ' ', '\0'};
|
||||
TestElement expect[] = {{0, text, 6, text, 2}, {0, text, 4, &text[3], 2}};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
EXPECT_EQ(expect[0].curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect[0].curLineSz, totalbuffer.CurLineSize());
|
||||
size_t cnt = sizeof(expect) / sizeof(expect[0]);
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
EXPECT_TRUE(totalbuffer.NextWord(' '));
|
||||
EXPECT_EQ(expect[i].curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect[i].curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithOnlyOneLineBuffer03, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', ' ', '\0'};
|
||||
TestElement expect = {0, text, 6, text, 6};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
EXPECT_EQ(expect.curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect.curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_TRUE(totalbuffer.NextWord('\0'));
|
||||
EXPECT_EQ(expect.curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect.curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithOnlyOneLineBuffer04, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', ' ', '\0'};
|
||||
TestElement expect = {0, text, 6, nullptr, 0};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
|
||||
EXPECT_EQ(expect.curLine, totalbuffer.CurLine());
|
||||
EXPECT_EQ(expect.curLineSz, totalbuffer.CurLineSize());
|
||||
EXPECT_FALSE(totalbuffer.NextWord('e'));
|
||||
EXPECT_EQ(expect.curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect.curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithMultipleLinesBuffer01, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', ' ', '\n', '1', '2', ' ', '3', '4', '5', ' ', '6', '\0'};
|
||||
TestElement expect[] = {
|
||||
{0, text, 6, text, 2}, {0, text, 6, &text[3], 2}, {0, text, 6, &text[7], 2}, {0, text, 4, &text[10], 3}};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
size_t expectWordCnt = 2;
|
||||
size_t curLineCnt = 0;
|
||||
do {
|
||||
for (size_t i = 0; i < expectWordCnt; i++) {
|
||||
EXPECT_TRUE(totalbuffer.NextWord(' '));
|
||||
EXPECT_EQ(expect[(curLineCnt * 2) + i].curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect[(curLineCnt * 2) + i].curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
curLineCnt++;
|
||||
} while (totalbuffer.NextLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithMultipleLinesBuffer02, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', ' ', '\n', '1', '2', ' ', '3', '4', '5', ' ', '6', '\0'};
|
||||
TestElement expect[] = {
|
||||
{0, text, 6, text, 2}, {0, text, 6, nullptr, 0}, {0, text, 6, &text[7], 2}, {0, text, 4, nullptr, 0}};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
size_t expectWordCnt = 2;
|
||||
size_t curLineCnt = 0;
|
||||
do {
|
||||
for (size_t i = 0; i < expectWordCnt; i++) {
|
||||
if (i == 0) {
|
||||
EXPECT_TRUE(totalbuffer.NextWord(' '));
|
||||
}
|
||||
if (i == 1) {
|
||||
EXPECT_FALSE(totalbuffer.NextWord('#'));
|
||||
}
|
||||
EXPECT_EQ(expect[(curLineCnt * 2) + i].curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect[(curLineCnt * 2) + i].curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
curLineCnt++;
|
||||
} while (totalbuffer.NextLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test NextWord().
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(BufferSplitterUnittest, NextWordWithMultipleLinesBuffer03, TestSize.Level1)
|
||||
{
|
||||
char text[] = {'a', 'b', ' ', 'c', 'd', ' ', '\n', '1', '2', ' ', '3', '4', '5', ' ', '6', '\0'};
|
||||
TestElement expect[] = {
|
||||
{0, text, 6, nullptr, 0}, {0, text, 6, text, 2}, {0, text, 6, nullptr, 0}, {0, text, 6, &text[7], 2}};
|
||||
int readsize = sizeof(text);
|
||||
BufferSplitter totalbuffer(text, readsize);
|
||||
size_t expectWordCnt = 2;
|
||||
size_t curLineCnt = 0;
|
||||
do {
|
||||
for (size_t i = 0; i < expectWordCnt; i++) {
|
||||
if (i == 0) {
|
||||
EXPECT_FALSE(totalbuffer.NextWord('#'));
|
||||
}
|
||||
if (i == 1) {
|
||||
EXPECT_TRUE(totalbuffer.NextWord(' '));
|
||||
}
|
||||
EXPECT_EQ(expect[(curLineCnt * 2) + i].curWord, totalbuffer.CurWord());
|
||||
EXPECT_EQ(expect[(curLineCnt * 2) + i].curWordSz, totalbuffer.CurWordSize());
|
||||
}
|
||||
curLineCnt++;
|
||||
} while (totalbuffer.NextLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test the scene that actually used,parse /proc/meminfo.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
namespace {
|
||||
char g_kMockMeminfo[] = R"(
|
||||
MemTotal: 16168736 kB
|
||||
MemFree: 7154492 kB
|
||||
MemAvailable: 15481028 kB
|
||||
Buffers: 2397540 kB
|
||||
Cached: 4711136 kB
|
||||
SwapCached: 27628 kB
|
||||
Active: 5556068 kB
|
||||
Inactive: 1644560 kB
|
||||
Active(anon): 62580 kB
|
||||
Inactive(anon): 43352 kB
|
||||
Active(file): 5493488 kB
|
||||
Inactive(file): 1601208 kB
|
||||
Unevictable: 388 kB
|
||||
Mlocked: 0 kB
|
||||
SwapTotal: 16777180 kB
|
||||
SwapFree: 16500700 kB
|
||||
Dirty: 0 kB
|
||||
Writeback: 0 kB
|
||||
AnonPages: 87672 kB
|
||||
Mapped: 116988 kB
|
||||
Shmem: 13980 kB
|
||||
KReclaimable: 1568904 kB
|
||||
Slab: 1641176 kB
|
||||
SReclaimable: 1568904 kB
|
||||
SUnreclaim: 72272 kB
|
||||
KernelStack: 7008 kB
|
||||
PageTables: 28244 kB
|
||||
NFS_Unstable: 0 kB
|
||||
Bounce: 0 kB
|
||||
WritebackTmp: 0 kB
|
||||
CommitLimit: 24861548 kB
|
||||
Committed_AS: 2569488 kB
|
||||
VmallocTotal: 34359738367 kB
|
||||
VmallocUsed: 34260 kB
|
||||
VmallocChunk: 0 kB
|
||||
Percpu: 2912 kB
|
||||
HardwareCorrupted: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FileHugePages: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
CmaTotal: 0 kB
|
||||
CmaFree: 0 kB
|
||||
HugePages_Total: 0
|
||||
HugePages_Free: 0
|
||||
HugePages_Rsvd: 0
|
||||
HugePages_Surp: 0
|
||||
Hugepagesize: 2048 kB
|
||||
Hugetlb: 0 kB
|
||||
DirectMap4k: 1997488 kB
|
||||
DirectMap2M: 14548992 kB
|
||||
DirectMap1G: 0 kB)";
|
||||
}
|
||||
|
||||
HWTEST_F(BufferSplitterUnittest, MemInfoBufferTEST, TestSize.Level1)
|
||||
{
|
||||
int readsize = sizeof(g_kMockMeminfo);
|
||||
BufferSplitter totalbuffer(g_kMockMeminfo, readsize);
|
||||
|
||||
struct CStrCmp {
|
||||
bool operator()(const char* a, const char* b) const
|
||||
{
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
std::map<const char*, int, CStrCmp> meminfo_counters_ = {{"MemTotal", 16168736},
|
||||
{"Active", 5556068},
|
||||
{"Inactive(anon)", 43352},
|
||||
{"HugePages_Total", 0},
|
||||
{"DirectMap1G", 0}};
|
||||
|
||||
do {
|
||||
if (!totalbuffer.NextWord(':')) {
|
||||
continue;
|
||||
}
|
||||
const_cast<char *>(totalbuffer.CurWord())[totalbuffer.CurWordSize()] = '\0';
|
||||
auto it = meminfo_counters_.find(totalbuffer.CurWord());
|
||||
if (it == meminfo_counters_.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int counter_id = it->second;
|
||||
if (!totalbuffer.NextWord(' ')) {
|
||||
continue;
|
||||
}
|
||||
auto value = static_cast<uint64_t>(strtoll(totalbuffer.CurWord(), nullptr, 10));
|
||||
EXPECT_EQ((uint64_t)counter_id, value);
|
||||
} while (totalbuffer.NextLine());
|
||||
}
|
||||
} // namespace
|
579
device/plugins/memory_plugin/test/unittest/memory_data_plugin_unittest.cpp
Executable file
579
device/plugins/memory_plugin/test/unittest/memory_data_plugin_unittest.cpp
Executable file
@ -0,0 +1,579 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <hwext/gtest-ext.h>
|
||||
#include <hwext/gtest-tag.h>
|
||||
|
||||
#include "memory_data_plugin.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
const std::string DEFAULT_TEST_PATH("./");
|
||||
#else
|
||||
const std::string DEFAULT_TEST_PATH("/data/local/tmp/");
|
||||
#endif
|
||||
constexpr uint32_t BUF_SIZE = 4 * 1024 * 1024;
|
||||
constexpr uint32_t BIT_WIDTH = 35;
|
||||
|
||||
std::string g_path;
|
||||
const std::vector<int> g_expectPidList = {
|
||||
1, 2, 11
|
||||
};
|
||||
|
||||
struct TestElement {
|
||||
int32_t pid;
|
||||
std::string name;
|
||||
// data from /proc/$pid/stat
|
||||
uint64_t vm_size_kb;
|
||||
uint64_t vm_rss_kb;
|
||||
uint64_t rss_anon_kb;
|
||||
uint64_t rss_file_kb;
|
||||
uint64_t rss_shmem_kb;
|
||||
uint64_t vm_swap_kb;
|
||||
uint64_t vm_locked_kb;
|
||||
uint64_t vm_hwm_kb;
|
||||
int64_t oom_score_adj;
|
||||
|
||||
uint64_t java_heap;
|
||||
uint64_t native_heap;
|
||||
uint64_t code;
|
||||
uint64_t stack;
|
||||
uint64_t graphics;
|
||||
uint64_t private_other;
|
||||
};
|
||||
|
||||
TestElement g_singlepid = {-1, "null", 0, 0};
|
||||
TestElement g_pidtarget[] = {
|
||||
{1, "systemd", 226208, 9388, 2984, 6404, 0, 0, 0, 9616, -1, 3036, 4256, 288, 748, 0, 1388},
|
||||
{2, "kthreadd", 0, 0, 0, 0, 0, 0, 0, 0, -100, 3036, 4260, 336, 760, 0, 4204},
|
||||
{11, "rcu_sched", 0, 0, 0, 0, 0, 0, 0, 0, 0, 3036, 4272, 392, 772, 0, 7168},
|
||||
};
|
||||
|
||||
unsigned long g_meminfo[] = {16168696, 1168452, 12363564, 2726188, 7370484, 29260, 8450388, 4807668,
|
||||
2535372, 658832, 4148836, 132, 0, 63999996, 62211580, 0};
|
||||
std::string GetFullPath(std::string path);
|
||||
|
||||
class MemoryDataPluginTest : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase();
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
if (access(g_path.c_str(), F_OK) == 0) {
|
||||
std::string str = "rm -rf " + GetFullPath(DEFAULT_TEST_PATH) + "utresources";
|
||||
printf("TearDown--> %s\r\n", str.c_str());
|
||||
system(str.c_str());
|
||||
}
|
||||
}
|
||||
void SetUp() {}
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
string Getexepath()
|
||||
{
|
||||
char buf[PATH_MAX] = "";
|
||||
std::string path = "/proc/self/exe";
|
||||
size_t rslt = readlink(path.c_str(), buf, sizeof(buf));
|
||||
if (rslt < 0 || (rslt >= sizeof(buf))) {
|
||||
return "";
|
||||
}
|
||||
buf[rslt] = '\0';
|
||||
for (int i = rslt; i >= 0; i--) {
|
||||
if (buf[i] == '/') {
|
||||
buf[i + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void MyPrintfProcessMemoryInfo(MemoryData memoryData)
|
||||
{
|
||||
int index = memoryData.processesinfo_size();
|
||||
for (int i = 0; i < index; ++i) {
|
||||
ProcessMemoryInfo it = memoryData.processesinfo(i);
|
||||
std::cout << it.pid() << "\t";
|
||||
std::cout << std::setw(BIT_WIDTH) << std::setfill(' ') << it.name().c_str() << "\t";
|
||||
std::cout << it.vm_size_kb() << "\t";
|
||||
std::cout << it.vm_rss_kb() << "\t";
|
||||
std::cout << it.rss_anon_kb() << "\t";
|
||||
std::cout << it.rss_file_kb() << "\t";
|
||||
std::cout << it.rss_shmem_kb() << "\t";
|
||||
std::cout << it.vm_locked_kb() << "\t";
|
||||
std::cout << it.vm_hwm_kb() << "\t";
|
||||
|
||||
std::cout << it.oom_score_adj() << "\t";
|
||||
if (it.has_memsummary()) {
|
||||
std::cout << "appsummary:\t";
|
||||
AppSummary app = it.memsummary();
|
||||
std::cout << app.java_heap() << "\t";
|
||||
std::cout << app.native_heap() << "\t";
|
||||
std::cout << app.code() << "\t";
|
||||
std::cout << app.stack() << "\t";
|
||||
std::cout << app.graphics() << "\t";
|
||||
std::cout << app.private_other() << "\t";
|
||||
std::cout << app.system() << "\t";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginStub(std::vector<int> processList, MemoryDataPlugin& memoryPlugin, MemoryData& memoryData)
|
||||
{
|
||||
MemoryConfig protoConfig;
|
||||
int configSize;
|
||||
int ret;
|
||||
|
||||
// set config
|
||||
if (processList.size() != 0) {
|
||||
protoConfig.set_report_process_mem_info(true);
|
||||
protoConfig.set_report_app_mem_info(true);
|
||||
for (size_t i = 0; i < processList.size(); i++) {
|
||||
protoConfig.add_pid(processList.at(i));
|
||||
}
|
||||
} else {
|
||||
protoConfig.set_report_process_tree(true);
|
||||
}
|
||||
|
||||
// serialize
|
||||
configSize = protoConfig.ByteSizeLong();
|
||||
std::vector<uint8_t> configData(configSize);
|
||||
ret = protoConfig.SerializeToArray(configData.data(), configData.size());
|
||||
|
||||
// start
|
||||
ret = memoryPlugin.Start(configData.data(), configData.size());
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
printf("ut: serialize success start plugin ret = %d\n", ret);
|
||||
|
||||
// report
|
||||
std::vector<uint8_t> bufferData(BUF_SIZE);
|
||||
ret = memoryPlugin.Report(bufferData.data(), bufferData.size());
|
||||
if (ret > 0) {
|
||||
memoryData.ParseFromArray(bufferData.data(), ret);
|
||||
MyPrintfProcessMemoryInfo(memoryData);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pluginMeminfoStub(MemoryDataPlugin& memoryPlugin, MemoryData& memoryData)
|
||||
{
|
||||
MemoryConfig protoConfig;
|
||||
int configSize;
|
||||
int ret;
|
||||
|
||||
protoConfig.set_report_sysmem_mem_info(true);
|
||||
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_MEM_TOTAL);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_MEM_FREE);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_MEM_AVAILABLE);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_BUFFERS);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_CACHED);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_SWAP_CACHED);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_ACTIVE);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_INACTIVE);
|
||||
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_ACTIVE_ANON);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_INACTIVE_ANON);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_INACTIVE_FILE);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_UNEVICTABLE);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_MLOCKED);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_SWAP_TOTAL);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_SWAP_FREE);
|
||||
protoConfig.add_sys_meminfo_counters(SysMeminfoType::MEMINFO_DIRTY);
|
||||
|
||||
// serialize
|
||||
configSize = protoConfig.ByteSizeLong();
|
||||
std::vector<uint8_t> configData(configSize);
|
||||
ret = protoConfig.SerializeToArray(configData.data(), configData.size());
|
||||
|
||||
// start
|
||||
ret = memoryPlugin.Start(configData.data(), configData.size());
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
printf("ut: serialize success start plugin ret = %d\n", ret);
|
||||
|
||||
// report
|
||||
std::vector<uint8_t> bufferData(BUF_SIZE);
|
||||
ret = memoryPlugin.Report(bufferData.data(), bufferData.size());
|
||||
if (ret > 0) {
|
||||
memoryData.ParseFromArray(bufferData.data(), ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pluginWriteVmstat(MemoryDataPlugin& memoryPlugin, MemoryData& memoryData)
|
||||
{
|
||||
MemoryConfig protoConfig;
|
||||
int configSize;
|
||||
int ret;
|
||||
|
||||
protoConfig.set_report_sysmem_vmem_info(true);
|
||||
|
||||
// serialize
|
||||
configSize = protoConfig.ByteSizeLong();
|
||||
std::vector<uint8_t> configData(configSize);
|
||||
ret = protoConfig.SerializeToArray(configData.data(), configData.size());
|
||||
|
||||
// start
|
||||
ret = memoryPlugin.Start(configData.data(), configData.size());
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
printf("ut: serialize success start plugin ret = %d\n", ret);
|
||||
|
||||
// report
|
||||
std::vector<uint8_t> bufferData(BUF_SIZE);
|
||||
ret = memoryPlugin.Report(bufferData.data(), bufferData.size());
|
||||
if (ret > 0) {
|
||||
memoryData.ParseFromArray(bufferData.data(), ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pluginDumpsys(MemoryDataPlugin& memoryPlugin, MemoryData& memoryData)
|
||||
{
|
||||
MemoryConfig protoConfig;
|
||||
int configSize;
|
||||
int ret;
|
||||
|
||||
protoConfig.set_report_process_mem_info(true);
|
||||
protoConfig.set_report_app_mem_info(true);
|
||||
protoConfig.add_pid(1);
|
||||
protoConfig.set_report_app_mem_by_dumpsys(true);
|
||||
|
||||
// serialize
|
||||
configSize = protoConfig.ByteSizeLong();
|
||||
std::vector<uint8_t> configData(configSize);
|
||||
ret = protoConfig.SerializeToArray(configData.data(), configData.size());
|
||||
|
||||
// start
|
||||
ret = memoryPlugin.Start(configData.data(), configData.size());
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
printf("ut: serialize success start plugin ret = %d\n", ret);
|
||||
|
||||
// report
|
||||
std::vector<uint8_t> bufferData(BUF_SIZE);
|
||||
ret = memoryPlugin.Report(bufferData.data(), bufferData.size());
|
||||
if (ret > 0) {
|
||||
memoryData.ParseFromArray(bufferData.data(), ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GetFullPath(std::string path)
|
||||
{
|
||||
if (path.size() > 0 && path[0] != '/') {
|
||||
return Getexepath() + path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
bool CreatTestResource(std::string path, std::string exepath)
|
||||
{
|
||||
std::string str = "cp -r " + path + "utresources " + exepath;
|
||||
printf("CreatTestResource:%s\n", str.c_str());
|
||||
|
||||
pid_t status = system(str.c_str());
|
||||
if (-1 == status) {
|
||||
printf("system error!");
|
||||
} else {
|
||||
printf("exit status value = [0x%x]\n", status);
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
printf("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
printf("exit status = [%d]\n", WEXITSTATUS(status));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MemoryDataPluginTest::SetUpTestCase()
|
||||
{
|
||||
g_path = GetFullPath(DEFAULT_TEST_PATH);
|
||||
printf("g_path:%s\n", g_path.c_str());
|
||||
EXPECT_NE("", g_path);
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (DEFAULT_TEST_PATH != g_path) {
|
||||
if ((access(std::string(g_path + "utresources/proc").c_str(), F_OK) != 0) &&
|
||||
(access(std::string(DEFAULT_TEST_PATH + "utresources/proc").c_str(), F_OK) == 0)) {
|
||||
EXPECT_TRUE(CreatTestResource(DEFAULT_TEST_PATH, g_path));
|
||||
}
|
||||
g_path += "utresources/proc";
|
||||
}
|
||||
#else
|
||||
g_path += "utresources/proc";
|
||||
#endif
|
||||
printf("g_path:%s\n", g_path.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Test whether the path exists.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, Testpath, TestSize.Level1)
|
||||
{
|
||||
EXPECT_NE(g_path, "");
|
||||
printf("g_path:%s\n", g_path.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Pid list test in a specific directory.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, Testpidlist, TestSize.Level1)
|
||||
{
|
||||
MemoryDataPlugin* memoryPlugin = new MemoryDataPlugin();
|
||||
|
||||
printf("g_path:%s\n", g_path.c_str());
|
||||
DIR* dir = memoryPlugin->OpenDestDir(g_path.c_str());
|
||||
EXPECT_NE(nullptr, dir);
|
||||
|
||||
std::vector<int> cmpPidList;
|
||||
while (int32_t pid = memoryPlugin->GetValidPid(dir)) {
|
||||
printf("pid = %d\n", pid);
|
||||
cmpPidList.push_back(pid);
|
||||
}
|
||||
sort(cmpPidList.begin(), cmpPidList.end());
|
||||
closedir(dir);
|
||||
EXPECT_EQ(cmpPidList, g_expectPidList);
|
||||
delete memoryPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Mem information test for specific pid.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, Testpluginformeminfo, TestSize.Level1)
|
||||
{
|
||||
MemoryDataPlugin memoryPlugin;
|
||||
MemoryData memoryData;
|
||||
memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
|
||||
printf("Testpluginformeminfo:setPath=%s\n", g_path.c_str());
|
||||
EXPECT_TRUE(pluginMeminfoStub(memoryPlugin, memoryData));
|
||||
|
||||
int index = memoryData.meminfo().size();
|
||||
EXPECT_EQ(16, index);
|
||||
printf("Testpluginformeminfo:index=%d\n", index);
|
||||
for (int i = 0; i < index; ++i) {
|
||||
EXPECT_EQ(g_meminfo[i], memoryData.meminfo(i).value());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// stop
|
||||
memoryPlugin.Stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: pid list information test for specific pid.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, Testpluginforsinglepid, TestSize.Level1)
|
||||
{
|
||||
MemoryDataPlugin memoryPlugin;
|
||||
MemoryData memoryData;
|
||||
std::vector<int> pid;
|
||||
pid.push_back(5);
|
||||
memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
|
||||
printf("Testpluginforsinglepid:setPath=%s\n", g_path.c_str());
|
||||
EXPECT_TRUE(PluginStub(pid, memoryPlugin, memoryData));
|
||||
int index = memoryData.processesinfo_size();
|
||||
EXPECT_EQ(1, index);
|
||||
printf("Testpluginforsinglepid:index=%d\n", index);
|
||||
|
||||
ProcessMemoryInfo it = memoryData.processesinfo(0);
|
||||
EXPECT_EQ(g_singlepid.pid, it.pid());
|
||||
printf("pid=%d\r\n", it.pid());
|
||||
EXPECT_EQ(g_singlepid.name, it.name());
|
||||
EXPECT_EQ(g_singlepid.vm_size_kb, it.vm_size_kb());
|
||||
EXPECT_EQ(g_singlepid.vm_rss_kb, it.vm_rss_kb());
|
||||
EXPECT_EQ(g_singlepid.rss_anon_kb, it.rss_anon_kb());
|
||||
EXPECT_EQ(g_singlepid.rss_file_kb, it.rss_file_kb());
|
||||
EXPECT_EQ(g_singlepid.rss_shmem_kb, it.rss_shmem_kb());
|
||||
EXPECT_EQ(g_singlepid.vm_locked_kb, it.vm_locked_kb());
|
||||
EXPECT_EQ(g_singlepid.vm_hwm_kb, it.vm_hwm_kb());
|
||||
|
||||
EXPECT_EQ(g_singlepid.oom_score_adj, it.oom_score_adj());
|
||||
|
||||
EXPECT_TRUE(it.has_memsummary());
|
||||
AppSummary app = it.memsummary();
|
||||
EXPECT_EQ(g_singlepid.java_heap, app.java_heap());
|
||||
EXPECT_EQ(g_singlepid.native_heap, app.native_heap());
|
||||
EXPECT_EQ(g_singlepid.code, app.code());
|
||||
EXPECT_EQ(g_singlepid.stack, app.stack());
|
||||
EXPECT_EQ(g_singlepid.graphics, app.graphics());
|
||||
EXPECT_EQ(g_singlepid.private_other, app.private_other());
|
||||
|
||||
// stop
|
||||
memoryPlugin.Stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: pid list information test for specific pids.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, Testpluginforpids, TestSize.Level1)
|
||||
{
|
||||
std::vector<int> cmpPidList = g_expectPidList;
|
||||
EXPECT_NE((size_t)0, cmpPidList.size());
|
||||
MemoryDataPlugin memoryPlugin;
|
||||
MemoryData memoryData;
|
||||
memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
|
||||
printf("Testpluginforpids:setPath=%s\n", g_path.c_str());
|
||||
EXPECT_TRUE(PluginStub(cmpPidList, memoryPlugin, memoryData));
|
||||
int index = memoryData.processesinfo_size();
|
||||
EXPECT_EQ(3, index);
|
||||
printf("Testpluginforpids:index=%d\n", index);
|
||||
for (int i = 0; i < index; ++i) {
|
||||
ProcessMemoryInfo it = memoryData.processesinfo(i);
|
||||
EXPECT_EQ(g_pidtarget[i].pid, it.pid());
|
||||
printf("%d:pid=%d\r\n", i, it.pid());
|
||||
EXPECT_EQ(g_pidtarget[i].name, it.name());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_size_kb, it.vm_size_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_rss_kb, it.vm_rss_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].rss_anon_kb, it.rss_anon_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].rss_file_kb, it.rss_file_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].rss_shmem_kb, it.rss_shmem_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_locked_kb, it.vm_locked_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_hwm_kb, it.vm_hwm_kb());
|
||||
|
||||
EXPECT_EQ(g_pidtarget[i].oom_score_adj, it.oom_score_adj());
|
||||
|
||||
EXPECT_TRUE(it.has_memsummary());
|
||||
}
|
||||
// stop
|
||||
memoryPlugin.Stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: pid list information test for process tree.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, Testpluginforlist, TestSize.Level1)
|
||||
{
|
||||
std::vector<int> cmpPidList = g_expectPidList;
|
||||
EXPECT_NE((size_t)0, cmpPidList.size());
|
||||
MemoryDataPlugin memoryPlugin;
|
||||
std::vector<int> pid;
|
||||
MemoryData memoryData;
|
||||
memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
|
||||
printf("Testpluginforlist:setPath=%s\n", g_path.c_str());
|
||||
EXPECT_TRUE(PluginStub(pid, memoryPlugin, memoryData));
|
||||
int index = memoryData.processesinfo_size();
|
||||
EXPECT_EQ(3, index);
|
||||
printf("Testpluginforlist:index=%d, pidsize=", index);
|
||||
std::cout << pid.size() << std::endl;
|
||||
for (int i = 0; i < index; ++i) {
|
||||
ProcessMemoryInfo it = memoryData.processesinfo(i);
|
||||
EXPECT_EQ(g_pidtarget[i].pid, it.pid());
|
||||
printf("%d:pid=%d\r\n", i, it.pid());
|
||||
EXPECT_EQ(g_pidtarget[i].name, it.name());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_size_kb, it.vm_size_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_rss_kb, it.vm_rss_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].rss_anon_kb, it.rss_anon_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].rss_file_kb, it.rss_file_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].rss_shmem_kb, it.rss_shmem_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_locked_kb, it.vm_locked_kb());
|
||||
EXPECT_EQ(g_pidtarget[i].vm_hwm_kb, it.vm_hwm_kb());
|
||||
|
||||
EXPECT_EQ(g_pidtarget[i].oom_score_adj, it.oom_score_adj());
|
||||
|
||||
EXPECT_TRUE(!it.has_memsummary());
|
||||
}
|
||||
// stop
|
||||
memoryPlugin.Stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Smaps stats info test for specific pids.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, TestSmapsStatsInfo, TestSize.Level1)
|
||||
{
|
||||
SmapsStats smap(std::string(g_path + "/"));
|
||||
for (size_t i = 0; i < g_expectPidList.size(); i++) {
|
||||
EXPECT_TRUE(smap.ParseMaps(g_expectPidList[i]));
|
||||
EXPECT_EQ(g_pidtarget[i].java_heap, (uint64_t)(smap.GetProcessJavaHeap()));
|
||||
EXPECT_EQ(g_pidtarget[i].native_heap, (uint64_t)(smap.GetProcessNativeHeap()));
|
||||
EXPECT_EQ(g_pidtarget[i].code, (uint64_t)(smap.GetProcessCode()));
|
||||
EXPECT_EQ(g_pidtarget[i].stack, (uint64_t)(smap.GetProcessStack()));
|
||||
EXPECT_EQ(g_pidtarget[i].graphics, (uint64_t)(smap.GetProcessGraphics()));
|
||||
EXPECT_EQ(g_pidtarget[i].private_other, (uint64_t)(smap.GetProcessPrivateOther()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Vmstat info test for specific pids.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, TestpluginWriteVmstat, TestSize.Level1)
|
||||
{
|
||||
MemoryDataPlugin memoryPlugin;
|
||||
MemoryData memoryData;
|
||||
memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
|
||||
printf("Testpluginformeminfo:setPath=%s\n", g_path.c_str());
|
||||
EXPECT_FALSE(pluginWriteVmstat(memoryPlugin, memoryData));
|
||||
// stop
|
||||
memoryPlugin.Stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: memory plugin
|
||||
* @tc.desc: Get information through Dumpsys.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(MemoryDataPluginTest, TestpluginDumpsys, TestSize.Level1)
|
||||
{
|
||||
MemoryDataPlugin memoryPlugin;
|
||||
MemoryData memoryData;
|
||||
memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
|
||||
printf("Testpluginformeminfo:setPath=%s\n", g_path.c_str());
|
||||
EXPECT_TRUE(pluginDumpsys(memoryPlugin, memoryData));
|
||||
std::string line = "01234567890";
|
||||
memoryPlugin.ParseNumber(line);
|
||||
// stop
|
||||
memoryPlugin.Stop();
|
||||
}
|
||||
} // namespace
|
32
device/plugins/memory_plugin/test/utresources/ohos_test.xml
Normal file
32
device/plugins/memory_plugin/test/utresources/ohos_test.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<configuration ver="2.0">
|
||||
<target name="memdataplugin_ut">
|
||||
<preparer>
|
||||
<option name="push" value="proc/1/oom_score_adj -> /data/local/tmp/utresources/proc/1/" src="res"/>
|
||||
<option name="push" value="proc/1/smaps -> /data/local/tmp/utresources/proc/1/" src="res"/>
|
||||
<option name="push" value="proc/1/status -> /data/local/tmp/utresources/proc/1/" src="res"/>
|
||||
<option name="push" value="proc/2/oom_score_adj -> /data/local/tmp/utresources/proc/2/" src="res"/>
|
||||
<option name="push" value="proc/2/smaps -> /data/local/tmp/utresources/proc/2/" src="res"/>
|
||||
<option name="push" value="proc/2/status -> /data/local/tmp/utresources/proc/2/" src="res"/>
|
||||
<option name="push" value="proc/11/oom_score_adj -> /data/local/tmp/utresources/proc/11/" src="res"/>
|
||||
<option name="push" value="proc/11/smaps -> /data/local/tmp/utresources/proc/11/" src="res"/>
|
||||
<option name="push" value="proc/11/status -> /data/local/tmp/utresources/proc/11/" src="res"/>
|
||||
<option name="push" value="proc/cmdline -> /data/local/tmp/utresources/proc/" src="res"/>
|
||||
<option name="push" value="proc/meminfo -> /data/local/tmp/utresources/proc/" src="res"/>
|
||||
</preparer>
|
||||
</target>
|
||||
</configuration>
|
1
device/plugins/memory_plugin/test/utresources/proc/1/oom_score_adj
Executable file
1
device/plugins/memory_plugin/test/utresources/proc/1/oom_score_adj
Executable file
@ -0,0 +1 @@
|
||||
-1
|
46233
device/plugins/memory_plugin/test/utresources/proc/1/smaps
Executable file
46233
device/plugins/memory_plugin/test/utresources/proc/1/smaps
Executable file
File diff suppressed because it is too large
Load Diff
55
device/plugins/memory_plugin/test/utresources/proc/1/status
Executable file
55
device/plugins/memory_plugin/test/utresources/proc/1/status
Executable file
@ -0,0 +1,55 @@
|
||||
Name: systemd
|
||||
Umask: 0000
|
||||
State: S (sleeping)
|
||||
Tgid: 1
|
||||
Ngid: 0
|
||||
Pid: 1
|
||||
PPid: 0
|
||||
TracerPid: 0
|
||||
Uid: 0 0 0 0
|
||||
Gid: 0 0 0 0
|
||||
FDSize: 512
|
||||
Groups:
|
||||
NStgid: 1
|
||||
NSpid: 1
|
||||
NSpgid: 1
|
||||
NSsid: 1
|
||||
VmPeak: 290996 kB
|
||||
VmSize: 226208 kB
|
||||
VmLck: 0 kB
|
||||
VmPin: 0 kB
|
||||
VmHWM: 9616 kB
|
||||
VmRSS: 9388 kB
|
||||
RssAnon: 2984 kB
|
||||
RssFile: 6404 kB
|
||||
RssShmem: 0 kB
|
||||
VmData: 19420 kB
|
||||
VmStk: 132 kB
|
||||
VmExe: 1344 kB
|
||||
VmLib: 10048 kB
|
||||
VmPTE: 212 kB
|
||||
VmSwap: 164 kB
|
||||
HugetlbPages: 0 kB
|
||||
CoreDumping: 0
|
||||
THP_enabled: 1
|
||||
Threads: 1
|
||||
SigQ: 0/62970
|
||||
SigPnd: 0000000000000000
|
||||
ShdPnd: 0000000000000000
|
||||
SigBlk: 7be3c0fe28014a03
|
||||
SigIgn: 0000000000001000
|
||||
SigCgt: 00000001800004ec
|
||||
CapInh: 0000000000000000
|
||||
CapPrm: 0000003fffffffff
|
||||
CapEff: 0000003fffffffff
|
||||
CapBnd: 0000003fffffffff
|
||||
CapAmb: 0000000000000000
|
||||
NoNewPrivs: 0
|
||||
Seccomp: 0
|
||||
Speculation_Store_Bypass: thread vulnerable
|
||||
Cpus_allowed: 3f
|
||||
Cpus_allowed_list: 0-5
|
||||
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
|
||||
Mems_allowed_list: 0
|
||||
voluntary_ctxt_switches: 78718
|
||||
nonvoluntary_ctxt_switches: 3443
|
1
device/plugins/memory_plugin/test/utresources/proc/11/oom_score_adj
Executable file
1
device/plugins/memory_plugin/test/utresources/proc/11/oom_score_adj
Executable file
@ -0,0 +1 @@
|
||||
0
|
713
device/plugins/memory_plugin/test/utresources/proc/11/smaps
Executable file
713
device/plugins/memory_plugin/test/utresources/proc/11/smaps
Executable file
@ -0,0 +1,713 @@
|
||||
564044f07000-564044f08000 r-xp 00000000 08:01 4587541 test/run
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me dw sd
|
||||
564045107000-564045108000 r--p 00000000 08:01 4587541 test/run
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me dw ac sd
|
||||
564045108000-564045109000 rw-p 00001000 08:01 4587541 test/run
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me dw ac sd
|
||||
564045dbe000-564045ddf000 rw-p 00000000 00:00 0 [heap]
|
||||
Size: 132 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 12 kB
|
||||
Pss: 12 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 12 kB
|
||||
Referenced: 12 kB
|
||||
Anonymous: 12 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f46756f6000-7f467570d000 r-xp 00000000 08:01 923931 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
||||
Size: 92 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 92 kB
|
||||
Pss: 20 kB
|
||||
Shared_Clean: 92 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 92 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me sd
|
||||
7f467570d000-7f467590c000 ---p 00017000 08:01 923931 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
||||
Size: 2044 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: mr mw me sd
|
||||
7f467590c000-7f467590d000 r--p 00016000 08:01 923931 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me ac sd
|
||||
7f467590d000-7f467590e000 rw-p 00017000 08:01 923931 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f467590e000-7f4675aab000 r-xp 00000000 08:01 929314 /lib/x86_64-linux-gnu/libm-2.27.so
|
||||
Size: 1652 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 300 kB
|
||||
Pss: 51 kB
|
||||
Shared_Clean: 300 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 300 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me sd
|
||||
7f4675aab000-7f4675caa000 ---p 0019d000 08:01 929314 /lib/x86_64-linux-gnu/libm-2.27.so
|
||||
Size: 2044 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: mr mw me sd
|
||||
7f4675caa000-7f4675cab000 r--p 0019c000 08:01 929314 /lib/x86_64-linux-gnu/libm-2.27.so
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me ac sd
|
||||
7f4675cab000-7f4675cac000 rw-p 0019d000 08:01 929314 /lib/x86_64-linux-gnu/libm-2.27.so
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f4675cac000-7f4675e93000 r-xp 00000000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 1948 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 1136 kB
|
||||
Pss: 19 kB
|
||||
Shared_Clean: 1136 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 1136 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me sd
|
||||
7f4675e93000-7f4676093000 ---p 001e7000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 2048 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: mr mw me sd
|
||||
7f4676093000-7f4676097000 r--p 001e7000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 16 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 16 kB
|
||||
Pss: 16 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 16 kB
|
||||
Referenced: 16 kB
|
||||
Anonymous: 16 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me ac sd
|
||||
7f4676097000-7f4676099000 rw-p 001eb000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 8 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 8 kB
|
||||
Pss: 8 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 8 kB
|
||||
Referenced: 8 kB
|
||||
Anonymous: 8 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f4676099000-7f467609d000 rw-p 00000000 00:00 0
|
||||
Size: 16 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 12 kB
|
||||
Pss: 12 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 12 kB
|
||||
Referenced: 12 kB
|
||||
Anonymous: 12 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f467609d000-7f4676216000 r-xp 00000000 08:01 1190514 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
|
||||
Size: 1508 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 780 kB
|
||||
Pss: 301 kB
|
||||
Shared_Clean: 780 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 780 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me sd
|
||||
7f4676216000-7f4676416000 ---p 00179000 08:01 1190514 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
|
||||
Size: 2048 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: mr mw me sd
|
||||
7f4676416000-7f4676420000 r--p 00179000 08:01 1190514 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
|
||||
Size: 40 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 40 kB
|
||||
Pss: 40 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 40 kB
|
||||
Referenced: 40 kB
|
||||
Anonymous: 40 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me ac sd
|
||||
7f4676420000-7f4676422000 rw-p 00183000 08:01 1190514 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
|
||||
Size: 8 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 8 kB
|
||||
Pss: 8 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 8 kB
|
||||
Referenced: 8 kB
|
||||
Anonymous: 8 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f4676422000-7f4676426000 rw-p 00000000 00:00 0
|
||||
Size: 16 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f4676426000-7f467644f000 r-xp 00000000 08:01 927476 /lib/x86_64-linux-gnu/ld-2.27.so
|
||||
Size: 164 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 164 kB
|
||||
Pss: 3 kB
|
||||
Shared_Clean: 164 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 164 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me dw sd
|
||||
7f4676634000-7f467663a000 rw-p 00000000 00:00 0
|
||||
Size: 24 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 24 kB
|
||||
Pss: 24 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 24 kB
|
||||
Referenced: 24 kB
|
||||
Anonymous: 24 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7f467664f000-7f4676650000 r--p 00029000 08:01 927476 /lib/x86_64-linux-gnu/ld-2.27.so
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me dw ac sd
|
||||
7f4676650000-7f4676651000 rw-p 0002a000 08:01 927476 /lib/x86_64-linux-gnu/ld-2.27.so
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me dw ac sd
|
||||
7f4676651000-7f4676652000 rw-p 00000000 00:00 0
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7ffe45c9a000-7ffe45cbb000 rw-p 00000000 00:00 0 [stack]
|
||||
Size: 132 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 12 kB
|
||||
Pss: 12 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 12 kB
|
||||
Referenced: 12 kB
|
||||
Anonymous: 12 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me gd ac
|
||||
7ffe45d41000-7ffe45d44000 r--p 00000000 00:00 0 [vvar]
|
||||
Size: 12 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr pf io de dd sd
|
||||
7ffe45d44000-7ffe45d45000 r-xp 00000000 00:00 0 [vdso]
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 4 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me de sd
|
||||
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: ex
|
37
device/plugins/memory_plugin/test/utresources/proc/11/status
Executable file
37
device/plugins/memory_plugin/test/utresources/proc/11/status
Executable file
@ -0,0 +1,37 @@
|
||||
Name: rcu_sched
|
||||
Umask: 0000
|
||||
State: I (idle)
|
||||
Tgid: 11
|
||||
Ngid: 0
|
||||
Pid: 11
|
||||
PPid: 2
|
||||
TracerPid: 0
|
||||
Uid: 0 0 0 0
|
||||
Gid: 0 0 0 0
|
||||
FDSize: 64
|
||||
Groups:
|
||||
NStgid: 11
|
||||
NSpid: 11
|
||||
NSpgid: 0
|
||||
NSsid: 0
|
||||
Threads: 1
|
||||
SigQ: 0/62967
|
||||
SigPnd: 0000000000000000
|
||||
ShdPnd: 0000000000000000
|
||||
SigBlk: 0000000000000000
|
||||
SigIgn: ffffffffffffffff
|
||||
SigCgt: 0000000000000000
|
||||
CapInh: 0000000000000000
|
||||
CapPrm: 0000003fffffffff
|
||||
CapEff: 0000003fffffffff
|
||||
CapBnd: 0000003fffffffff
|
||||
CapAmb: 0000000000000000
|
||||
NoNewPrivs: 0
|
||||
Seccomp: 0
|
||||
Speculation_Store_Bypass: thread vulnerable
|
||||
Cpus_allowed: 3f
|
||||
Cpus_allowed_list: 0-5
|
||||
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
|
||||
Mems_allowed_list: 0
|
||||
voluntary_ctxt_switches: 18962428
|
||||
nonvoluntary_ctxt_switches: 39
|
1
device/plugins/memory_plugin/test/utresources/proc/2/oom_score_adj
Executable file
1
device/plugins/memory_plugin/test/utresources/proc/2/oom_score_adj
Executable file
@ -0,0 +1 @@
|
||||
-100
|
414
device/plugins/memory_plugin/test/utresources/proc/2/smaps
Executable file
414
device/plugins/memory_plugin/test/utresources/proc/2/smaps
Executable file
@ -0,0 +1,414 @@
|
||||
5637ebe15000-5637ebe16000 r-xp 00000000 08:01 4587541 test/run
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 4 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me dw sd
|
||||
5637ec015000-5637ec016000 r--p 00000000 08:01 4587541 test/run
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me dw ac sd
|
||||
5637ec016000-5637ec017000 rw-p 00001000 08:01 4587541 test/run
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me dw ac sd
|
||||
5637ec60f000-5637ec630000 rw-p 00000000 00:00 0 [heap]
|
||||
Size: 132 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7fa384a9e000-7fa384c85000 r-xp 00000000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 1948 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 1200 kB
|
||||
Pss: 20 kB
|
||||
Shared_Clean: 1200 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 1200 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me sd
|
||||
7fa384c85000-7fa384e85000 ---p 001e7000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 2048 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: mr mw me sd
|
||||
7fa384e85000-7fa384e89000 r--p 001e7000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 16 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 16 kB
|
||||
Pss: 16 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 16 kB
|
||||
Referenced: 16 kB
|
||||
Anonymous: 16 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me ac sd
|
||||
7fa384e89000-7fa384e8b000 rw-p 001eb000 08:01 929310 /lib/x86_64-linux-gnu/libc-2.27.so
|
||||
Size: 8 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 8 kB
|
||||
Pss: 8 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 8 kB
|
||||
Referenced: 8 kB
|
||||
Anonymous: 8 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7fa384e8b000-7fa384e8f000 rw-p 00000000 00:00 0
|
||||
Size: 16 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 12 kB
|
||||
Pss: 12 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 12 kB
|
||||
Referenced: 12 kB
|
||||
Anonymous: 12 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7fa384e8f000-7fa384eb8000 r-xp 00000000 08:01 927476 /lib/x86_64-linux-gnu/ld-2.27.so
|
||||
Size: 164 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 164 kB
|
||||
Pss: 3 kB
|
||||
Shared_Clean: 164 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 164 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me dw sd
|
||||
7fa3850a1000-7fa3850a3000 rw-p 00000000 00:00 0
|
||||
Size: 8 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 8 kB
|
||||
Pss: 8 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 8 kB
|
||||
Referenced: 8 kB
|
||||
Anonymous: 8 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7fa3850b8000-7fa3850b9000 r--p 00029000 08:01 927476 /lib/x86_64-linux-gnu/ld-2.27.so
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr mw me dw ac sd
|
||||
7fa3850b9000-7fa3850ba000 rw-p 0002a000 08:01 927476 /lib/x86_64-linux-gnu/ld-2.27.so
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me dw ac sd
|
||||
7fa3850ba000-7fa3850bb000 rw-p 00000000 00:00 0
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 4 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 4 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 4 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me ac sd
|
||||
7ffc54ec0000-7ffc54ee1000 rw-p 00000000 00:00 0 [stack]
|
||||
Size: 132 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 12 kB
|
||||
Pss: 12 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 12 kB
|
||||
Referenced: 12 kB
|
||||
Anonymous: 12 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd wr mr mw me gd ac
|
||||
7ffc54f1c000-7ffc54f1f000 r--p 00000000 00:00 0 [vvar]
|
||||
Size: 12 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd mr pf io de dd sd
|
||||
7ffc54f1f000-7ffc54f20000 r-xp 00000000 00:00 0 [vdso]
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 4 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 4 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 4 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: rd ex mr mw me de sd
|
||||
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
|
||||
Size: 4 kB
|
||||
KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Rss: 0 kB
|
||||
Pss: 0 kB
|
||||
Shared_Clean: 0 kB
|
||||
Shared_Dirty: 0 kB
|
||||
Private_Clean: 0 kB
|
||||
Private_Dirty: 0 kB
|
||||
Referenced: 0 kB
|
||||
Anonymous: 0 kB
|
||||
LazyFree: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
Shared_Hugetlb: 0 kB
|
||||
Private_Hugetlb: 0 kB
|
||||
Swap: 0 kB
|
||||
SwapPss: 0 kB
|
||||
Locked: 0 kB
|
||||
THPeligible: 0
|
||||
VmFlags: ex
|
37
device/plugins/memory_plugin/test/utresources/proc/2/status
Executable file
37
device/plugins/memory_plugin/test/utresources/proc/2/status
Executable file
@ -0,0 +1,37 @@
|
||||
Name: kthreadd
|
||||
Umask: 0000
|
||||
State: S (sleeping)
|
||||
Tgid: 2
|
||||
Ngid: 0
|
||||
Pid: 2
|
||||
PPid: 0
|
||||
TracerPid: 0
|
||||
Uid: 0 0 0 0
|
||||
Gid: 0 0 0 0
|
||||
FDSize: 64
|
||||
Groups:
|
||||
NStgid: 2
|
||||
NSpid: 2
|
||||
NSpgid: 0
|
||||
NSsid: 0
|
||||
Threads: 1
|
||||
SigQ: 0/62970
|
||||
SigPnd: 0000000000000000
|
||||
ShdPnd: 0000000000000000
|
||||
SigBlk: 0000000000000000
|
||||
SigIgn: ffffffffffffffff
|
||||
SigCgt: 0000000000000000
|
||||
CapInh: 0000000000000000
|
||||
CapPrm: 0000003fffffffff
|
||||
CapEff: 0000003fffffffff
|
||||
CapBnd: 0000003fffffffff
|
||||
CapAmb: 0000000000000000
|
||||
NoNewPrivs: 0
|
||||
Seccomp: 0
|
||||
Speculation_Store_Bypass: thread vulnerable
|
||||
Cpus_allowed: 3f
|
||||
Cpus_allowed_list: 0-5
|
||||
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
|
||||
Mems_allowed_list: 0
|
||||
voluntary_ctxt_switches: 3372
|
||||
nonvoluntary_ctxt_switches: 1
|
0
device/plugins/memory_plugin/test/utresources/proc/cmdline
Executable file
0
device/plugins/memory_plugin/test/utresources/proc/cmdline
Executable file
53
device/plugins/memory_plugin/test/utresources/proc/meminfo
Executable file
53
device/plugins/memory_plugin/test/utresources/proc/meminfo
Executable file
@ -0,0 +1,53 @@
|
||||
MemTotal: 16168696 kB
|
||||
MemFree: 1168452 kB
|
||||
MemAvailable: 12363564 kB
|
||||
Buffers: 2726188 kB
|
||||
Cached: 7370484 kB
|
||||
SwapCached: 29260 kB
|
||||
Active: 8450388 kB
|
||||
Inactive: 4807668 kB
|
||||
Active(anon): 2535372 kB
|
||||
Inactive(anon): 658832 kB
|
||||
Active(file): 5915016 kB
|
||||
Inactive(file): 4148836 kB
|
||||
Unevictable: 132 kB
|
||||
Mlocked: 0 kB
|
||||
SwapTotal: 63999996 kB
|
||||
SwapFree: 62211580 kB
|
||||
Dirty: 0 kB
|
||||
Writeback: 0 kB
|
||||
AnonPages: 3142688 kB
|
||||
Mapped: 161520 kB
|
||||
Shmem: 32820 kB
|
||||
KReclaimable: 1468312 kB
|
||||
Slab: 1545180 kB
|
||||
SReclaimable: 1468312 kB
|
||||
SUnreclaim: 76868 kB
|
||||
KernelStack: 9200 kB
|
||||
PageTables: 46928 kB
|
||||
NFS_Unstable: 0 kB
|
||||
Bounce: 0 kB
|
||||
WritebackTmp: 0 kB
|
||||
CommitLimit: 72084344 kB
|
||||
Committed_AS: 7746304 kB
|
||||
VmallocTotal: 34359738367 kB
|
||||
VmallocUsed: 37652 kB
|
||||
VmallocChunk: 0 kB
|
||||
Percpu: 3200 kB
|
||||
HardwareCorrupted: 0 kB
|
||||
AnonHugePages: 0 kB
|
||||
ShmemHugePages: 0 kB
|
||||
ShmemPmdMapped: 0 kB
|
||||
FileHugePages: 0 kB
|
||||
FilePmdMapped: 0 kB
|
||||
CmaTotal: 0 kB
|
||||
CmaFree: 0 kB
|
||||
HugePages_Total: 0
|
||||
HugePages_Free: 0
|
||||
HugePages_Rsvd: 0
|
||||
HugePages_Surp: 0
|
||||
Hugepagesize: 2048 kB
|
||||
Hugetlb: 0 kB
|
||||
DirectMap4k: 1315504 kB
|
||||
DirectMap2M: 15230976 kB
|
||||
DirectMap1G: 0 kB
|
65
device/services/ipc/BUILD.gn
Executable file
65
device/services/ipc/BUILD.gn
Executable file
@ -0,0 +1,65 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../../base/config.gni")
|
||||
|
||||
ohos_source_set("ipc") {
|
||||
sources = [
|
||||
"src/client_connection.cpp",
|
||||
"src/client_map.cpp",
|
||||
"src/service_entry.cpp",
|
||||
"src/socket_context.cpp",
|
||||
"src/unix_socket_client.cpp",
|
||||
"src/unix_socket_server.cpp",
|
||||
]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"../../base/include",
|
||||
"//utils/native/base/include",
|
||||
]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
if (build_l2) {
|
||||
external_deps = [ "shared_library:libhilog" ]
|
||||
} else {
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
}
|
||||
}
|
||||
deps = [
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
"//utils/native/base:utilsbase",
|
||||
]
|
||||
public_configs = [ "../../base:hiprofiler_test_config" ]
|
||||
}
|
||||
|
||||
ohos_executable("protoc_gen_ipc") {
|
||||
sources = [
|
||||
"src/ipc_generator.cpp",
|
||||
"src/ipc_generator_impl.cpp",
|
||||
"src/main.cpp",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"include",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}",
|
||||
]
|
||||
public_configs = [ "../../base:hiprofiler_test_config" ]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
|
||||
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
|
||||
]
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
}
|
34
device/services/ipc/include/client_connection.h
Executable file
34
device/services/ipc/include/client_connection.h
Executable file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_CONNECTION_H
|
||||
#define CLIENT_CONNECTION_H
|
||||
|
||||
#include "service_entry.h"
|
||||
#include "socket_context.h"
|
||||
#include <cstdint>
|
||||
|
||||
class ClientConnection final : public SocketContext {
|
||||
public:
|
||||
ClientConnection(int sfd, ServiceEntry& serviceEntry);
|
||||
~ClientConnection();
|
||||
|
||||
int RawProtocolProc(uint32_t pnum, const int8_t* buf, const uint32_t size) override;
|
||||
|
||||
ServiceEntry* serviceEntry_;
|
||||
std::string protoServiceName_;
|
||||
};
|
||||
|
||||
#endif
|
37
device/services/ipc/include/client_map.h
Executable file
37
device/services/ipc/include/client_map.h
Executable file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_MAP_H
|
||||
#define CLIENT_MAP_H
|
||||
|
||||
#include "client_connection.h"
|
||||
#include <map>
|
||||
|
||||
class ServiceEntry;
|
||||
|
||||
class ClientMap {
|
||||
public:
|
||||
static ClientMap& GetInstance();
|
||||
int PutClientSocket(int socketFileDescriptor, ServiceEntry& p);
|
||||
int AutoRelease();
|
||||
|
||||
private:
|
||||
ClientMap();
|
||||
~ClientMap();
|
||||
|
||||
std::map<int, std::shared_ptr<ClientConnection>> socketClients_;
|
||||
};
|
||||
|
||||
#endif
|
40
device/services/ipc/include/ipc_generator.h
Executable file
40
device/services/ipc/include/ipc_generator.h
Executable file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef IPC_GENERATOR_H
|
||||
#define IPC_GENERATOR_H
|
||||
|
||||
#include "google/protobuf/compiler/code_generator.h"
|
||||
#include "google/protobuf/compiler/plugin.h"
|
||||
#include "google/protobuf/descriptor.h"
|
||||
#include "google/protobuf/io/coded_stream.h"
|
||||
#include "google/protobuf/io/zero_copy_stream.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class IpcGeneratorImpl;
|
||||
|
||||
class IpcGenerator : public google::protobuf::compiler::CodeGenerator {
|
||||
public:
|
||||
IpcGenerator();
|
||||
~IpcGenerator();
|
||||
bool Generate(const google::protobuf::FileDescriptor* file,
|
||||
const std::string& parameter,
|
||||
google::protobuf::compiler::GeneratorContext* context,
|
||||
std::string* error) const override;
|
||||
};
|
||||
|
||||
#endif
|
86
device/services/ipc/include/ipc_generator_impl.h
Normal file
86
device/services/ipc/include/ipc_generator_impl.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef IPC_GENERATOR_IMPL_H
|
||||
#define IPC_GENERATOR_IMPL_H
|
||||
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
class IpcServices {
|
||||
public:
|
||||
IpcServices()
|
||||
{
|
||||
methodCount_ = 0;
|
||||
}
|
||||
~IpcServices() {}
|
||||
std::string serviceName_;
|
||||
std::map<int, std::string> methodList_;
|
||||
std::map<int, std::string> requestList_;
|
||||
std::map<int, std::string> responseList_;
|
||||
int methodCount_;
|
||||
bool AddMethod(std::string method, std::string request, std::string response)
|
||||
{
|
||||
for (int i = 0; i < methodCount_; i++) {
|
||||
if (methodList_[i] == method) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
methodList_[methodCount_] = method;
|
||||
requestList_[methodCount_] = request;
|
||||
responseList_[methodCount_] = response;
|
||||
methodCount_++;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class IpcGeneratorImpl {
|
||||
public:
|
||||
IpcGeneratorImpl();
|
||||
~IpcGeneratorImpl();
|
||||
|
||||
std::string SetNames(std::string fileName, std::string packageName);
|
||||
bool AddService(std::string serviceName);
|
||||
bool AddServiceMethod(std::string serviceName,
|
||||
std::string methodName,
|
||||
std::string requestName,
|
||||
std::string responseName);
|
||||
|
||||
std::string GenHeader();
|
||||
std::string GenSource();
|
||||
|
||||
private:
|
||||
std::string fileName_ = "";
|
||||
std::string baseName_ = "";
|
||||
std::string packageName_ = "";
|
||||
std::string headFileName_ = "";
|
||||
|
||||
void GenerateHeader(std::string& header_str);
|
||||
|
||||
std::string GenSendResponseImpl(int servicep, const std::string& server_class_name);
|
||||
std::string GenOnResponseImpl(int servicep, const std::string& client_class_name);
|
||||
|
||||
std::string GenServiceCallImpl(int servicep, const std::string& server_class_name);
|
||||
std::string GenClientProcImpl(int servicep);
|
||||
std::string GenClientRequestImpl(int servicep, const std::string& client_class_name);
|
||||
std::string GenServiceProcImpl(int servicep);
|
||||
|
||||
std::map<int, IpcServices> serviceList_;
|
||||
int serviceCount_ = 0;
|
||||
|
||||
std::map<int, std::string> enumMessageDict_;
|
||||
};
|
||||
|
||||
#endif
|
34
device/services/ipc/include/service_base.h
Executable file
34
device/services/ipc/include/service_base.h
Executable file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SERVICE_BASE_H
|
||||
#define SERVICE_BASE_H
|
||||
|
||||
#include <mutex>
|
||||
|
||||
class SocketContext;
|
||||
|
||||
class ServiceBase {
|
||||
public:
|
||||
virtual ~ServiceBase() {}
|
||||
virtual bool ProtocolProc(SocketContext& poc, uint32_t pnum, const int8_t* buf, const uint32_t size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::timed_mutex mWait_;
|
||||
std::string serviceName_;
|
||||
};
|
||||
|
||||
#endif
|
59
device/services/ipc/include/service_entry.h
Executable file
59
device/services/ipc/include/service_entry.h
Executable file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SERVICE_ENTRY_H
|
||||
#define SERVICE_ENTRY_H
|
||||
|
||||
#include "service_base.h"
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
|
||||
static const uint32_t PROTOCOL_TYPE_FILTER = 0xF0000000;
|
||||
|
||||
enum ProtocolType {
|
||||
PROTOCOL_TYPE_RAW = 0,
|
||||
PROTOCOL_TYPE_PROTOBUF = 0x10000000,
|
||||
};
|
||||
|
||||
struct ProtocolHead {
|
||||
uint32_t protoType;
|
||||
uint32_t protoSize;
|
||||
int8_t datas[0];
|
||||
};
|
||||
|
||||
class UnixSocketServer;
|
||||
|
||||
class ServiceEntry {
|
||||
public:
|
||||
ServiceEntry();
|
||||
~ServiceEntry();
|
||||
|
||||
bool StartServer(const std::string& addrname);
|
||||
|
||||
bool RegisterService(ServiceBase& psb);
|
||||
|
||||
const ServiceBase* FindServiceByName(const std::string& service_name);
|
||||
|
||||
private:
|
||||
std::shared_ptr<UnixSocketServer> unixSocketServer_;
|
||||
|
||||
std::map<std::string, ServiceBase*> serviceMap_;
|
||||
};
|
||||
|
||||
uint64_t GetTimeMS();
|
||||
uint64_t GetTimeUS();
|
||||
uint64_t GetTimeNS();
|
||||
|
||||
#endif
|
72
device/services/ipc/include/socket_context.h
Executable file
72
device/services/ipc/include/socket_context.h
Executable file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SOCKET_CONTEXT_H
|
||||
#define SOCKET_CONTEXT_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <thread>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
const static char DEFAULT_UNIX_SOCKET_PATH[] = "hiprofiler_unix_socket";
|
||||
#else
|
||||
const static char DEFAULT_UNIX_SOCKET_PATH[] = "/data/local/tmp/hiprofiler_unix_socket";
|
||||
#endif
|
||||
|
||||
class SocketContext;
|
||||
class ServiceBase;
|
||||
class ClientMap;
|
||||
|
||||
enum ClientState {
|
||||
CLIENT_STAT_WORKING,
|
||||
CLIENT_STAT_WAIT_THREAD_EXIT,
|
||||
CLIENT_STAT_THREAD_EXITED,
|
||||
};
|
||||
|
||||
enum RawProtocol {
|
||||
RAW_PROTOCOL_POINTTO_SERVICE = 1,
|
||||
};
|
||||
struct RawPointToService {
|
||||
char serviceName_[64];
|
||||
};
|
||||
|
||||
class SocketContext {
|
||||
public:
|
||||
SocketContext();
|
||||
virtual ~SocketContext();
|
||||
|
||||
bool SendRaw(uint32_t pnum, const int8_t* data, uint32_t size, int sockfd = -1);
|
||||
bool SendProtobuf(uint32_t pnum, google::protobuf::Message& pmsg);
|
||||
bool SendFileDescriptor(int fd);
|
||||
int ReceiveFileDiscriptor();
|
||||
|
||||
protected:
|
||||
friend class ClientMap;
|
||||
int socketHandle_;
|
||||
bool CreateRecvThread();
|
||||
enum ClientState clientState_;
|
||||
uint64_t lastProcMS_;
|
||||
|
||||
ServiceBase* serviceBase_;
|
||||
|
||||
virtual int RawProtocolProc(uint32_t pnum, const int8_t* buf, const uint32_t size);
|
||||
|
||||
private:
|
||||
static void* UnixSocketRecv(void* pp);
|
||||
std::thread recvThread_;
|
||||
};
|
||||
|
||||
#endif
|
32
device/services/ipc/include/unix_socket_client.h
Executable file
32
device/services/ipc/include/unix_socket_client.h
Executable file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UNIX_SOCKET_CLIENT_H
|
||||
#define UNIX_SOCKET_CLIENT_H
|
||||
|
||||
#include "socket_context.h"
|
||||
#include <cstdint>
|
||||
|
||||
class ServiceBase;
|
||||
|
||||
class UnixSocketClient final : public SocketContext {
|
||||
public:
|
||||
UnixSocketClient();
|
||||
~UnixSocketClient();
|
||||
|
||||
bool Connect(const std::string addrname, ServiceBase& serviceBase);
|
||||
};
|
||||
|
||||
#endif
|
42
device/services/ipc/include/unix_socket_server.h
Executable file
42
device/services/ipc/include/unix_socket_server.h
Executable file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UNIX_SOCKET_SERVER_H
|
||||
#define UNIX_SOCKET_SERVER_H
|
||||
|
||||
#include "socket_context.h"
|
||||
#include <ostream>
|
||||
#include <thread>
|
||||
|
||||
class ServiceEntry;
|
||||
|
||||
class UnixSocketServer {
|
||||
public:
|
||||
UnixSocketServer();
|
||||
~UnixSocketServer();
|
||||
|
||||
int socketHandle_;
|
||||
bool StartServer(const std::string& addrname, ServiceEntry& p);
|
||||
|
||||
std::string sAddrName_;
|
||||
// private:
|
||||
ServiceEntry* serviceEntry_;
|
||||
|
||||
private:
|
||||
std::thread acceptThread_;
|
||||
static void* UnixSocketAccept(void* p);
|
||||
};
|
||||
|
||||
#endif
|
53
device/services/ipc/src/client_connection.cpp
Executable file
53
device/services/ipc/src/client_connection.cpp
Executable file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "client_connection.h"
|
||||
#include <cstdint>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include "logging.h"
|
||||
|
||||
ClientConnection::ClientConnection(int sfd, ServiceEntry& serviceEntry)
|
||||
{
|
||||
serviceBase_ = nullptr;
|
||||
socketHandle_ = sfd;
|
||||
clientState_ = CLIENT_STAT_WORKING;
|
||||
lastProcMS_ = GetTimeMS();
|
||||
serviceEntry_ = &serviceEntry;
|
||||
CreateRecvThread();
|
||||
}
|
||||
|
||||
ClientConnection::~ClientConnection()
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "Client Released");
|
||||
}
|
||||
|
||||
int ClientConnection::RawProtocolProc(uint32_t pnum, const int8_t* buf, const uint32_t size)
|
||||
{
|
||||
switch (pnum) {
|
||||
case RAW_PROTOCOL_POINTTO_SERVICE: {
|
||||
struct RawPointToService* prrs = (struct RawPointToService*)buf;
|
||||
protoServiceName_ = prrs->serviceName_;
|
||||
serviceBase_ = const_cast<ServiceBase*>(serviceEntry_->FindServiceByName(protoServiceName_));
|
||||
HILOG_INFO(LOG_CORE, "RAW_PROTOCOL_POINTTO_SERVICE %s", protoServiceName_.c_str());
|
||||
}
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
61
device/services/ipc/src/client_map.cpp
Executable file
61
device/services/ipc/src/client_map.cpp
Executable file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "client_map.h"
|
||||
#include <cstdio>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include "logging.h"
|
||||
|
||||
ClientMap& ClientMap::GetInstance()
|
||||
{
|
||||
static ClientMap instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
ClientMap::ClientMap() {}
|
||||
|
||||
ClientMap::~ClientMap() {}
|
||||
|
||||
int ClientMap::PutClientSocket(int socketFileDescriptor, ServiceEntry& p)
|
||||
{
|
||||
if (socketClients_.find(socketFileDescriptor) == socketClients_.end()) {
|
||||
socketClients_[socketFileDescriptor] = std::make_shared<ClientConnection>(socketFileDescriptor, p);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ClientMap::AutoRelease()
|
||||
{
|
||||
for (auto iter = socketClients_.begin(); iter != socketClients_.end(); ++iter) {
|
||||
auto p = iter->second;
|
||||
switch (p->clientState_) {
|
||||
case CLIENT_STAT_WORKING:
|
||||
break;
|
||||
case CLIENT_STAT_WAIT_THREAD_EXIT:
|
||||
break;
|
||||
case CLIENT_STAT_THREAD_EXITED:
|
||||
HILOG_INFO(LOG_CORE, "AutoRelease release %d", iter->first);
|
||||
socketClients_.erase(iter->first);
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
55
device/services/ipc/src/ipc_generator.cpp
Executable file
55
device/services/ipc/src/ipc_generator.cpp
Executable file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ipc_generator.h"
|
||||
#include "ipc_generator_impl.h"
|
||||
|
||||
IpcGenerator::IpcGenerator() {}
|
||||
|
||||
IpcGenerator::~IpcGenerator() {}
|
||||
|
||||
bool IpcGenerator::Generate(const google::protobuf::FileDescriptor* file,
|
||||
const std::string& parameter,
|
||||
google::protobuf::compiler::GeneratorContext* context,
|
||||
std::string* error) const
|
||||
{
|
||||
auto pcsp = std::make_shared<IpcGeneratorImpl>();
|
||||
std::string base_name = pcsp->SetNames(file->name(), file->package());
|
||||
|
||||
for (int i = 0; i < file->service_count(); i++) {
|
||||
const google::protobuf::ServiceDescriptor* service = file->service(i);
|
||||
pcsp->AddService(service->name());
|
||||
for (int j = 0; j < service->method_count(); j++) {
|
||||
const google::protobuf::MethodDescriptor* method = service->method(j);
|
||||
const google::protobuf::Descriptor* inputType = method->input_type();
|
||||
const google::protobuf::Descriptor* outputType = method->output_type();
|
||||
pcsp->AddServiceMethod(service->name(), method->name(), inputType->name(), outputType->name());
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> header_output(context->Open(base_name + ".ipc.h"));
|
||||
std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> source_output(context->Open(base_name + ".ipc.cc"));
|
||||
|
||||
::google::protobuf::io::CodedOutputStream header_out(header_output.get());
|
||||
::google::protobuf::io::CodedOutputStream source_out(source_output.get());
|
||||
|
||||
std::string header_str = pcsp->GenHeader();
|
||||
header_out.WriteString(header_str);
|
||||
|
||||
std::string source_str = pcsp->GenSource();
|
||||
source_out.WriteString(source_str);
|
||||
|
||||
return true;
|
||||
}
|
455
device/services/ipc/src/ipc_generator_impl.cpp
Normal file
455
device/services/ipc/src/ipc_generator_impl.cpp
Normal file
@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ipc_generator_impl.h"
|
||||
|
||||
IpcGeneratorImpl::IpcGeneratorImpl() {}
|
||||
|
||||
IpcGeneratorImpl::~IpcGeneratorImpl() {}
|
||||
|
||||
namespace {
|
||||
const std::string BASE_HEADER_STRING = R"(
|
||||
#pragma once
|
||||
|
||||
#include "#HEAD_FILE_NAME#.pb.h"
|
||||
#include "service_base.h"
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
|
||||
class SocketContext;
|
||||
class UnixSocketClient;
|
||||
|
||||
#PROTOCOL_ENUM#
|
||||
|
||||
class #SERVICE_CLASS_NAME#:public ServiceBase
|
||||
{
|
||||
public:
|
||||
#SERVICE_CLASS_NAME#();
|
||||
bool ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) override;
|
||||
#RESPONSE_DEFINE#
|
||||
};
|
||||
|
||||
class #CLIENT_CLASS_NAME#:public ServiceBase
|
||||
{
|
||||
public:
|
||||
#CLIENT_CLASS_NAME#();
|
||||
|
||||
std::shared_ptr<UnixSocketClient> unixSocketClient_;
|
||||
bool Connect(const std::string addrname);
|
||||
bool ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) override;
|
||||
google::protobuf::Message *presponse;
|
||||
uint32_t waitingFor;
|
||||
#VIRTUAL_RESPONSE_FUNC#
|
||||
};
|
||||
)";
|
||||
|
||||
const std::string BASE_SOURCE_STRING = R"(
|
||||
#include "#HEAD_FILE_NAME#.ipc.h"
|
||||
#include "#HEAD_FILE_NAME#.pb.h"
|
||||
#include "socket_context.h"
|
||||
#include "unix_socket_client.h"
|
||||
#include "unix_socket_server.h"
|
||||
#include <unistd.h>
|
||||
|
||||
namespace{
|
||||
const uint32_t WAIT_FOR_EVER=24*60*60*1000;
|
||||
}
|
||||
|
||||
#SERVICE_CLASS_NAME#::#SERVICE_CLASS_NAME#()
|
||||
{
|
||||
serviceName_="#SERVICE_NAME#";
|
||||
}
|
||||
|
||||
#RESPONSE_IMPLEMENT#
|
||||
|
||||
#SERVICE_PROTOCOL_PROC_FUNC#
|
||||
bool #SERVICE_CLASS_NAME#::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size)
|
||||
{
|
||||
switch (pnum) {
|
||||
#SERVICE_PROTOCOL_PROC#
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#CLIENT_CLASS_NAME#::#CLIENT_CLASS_NAME#()
|
||||
{
|
||||
unixSocketClient_=nullptr;
|
||||
serviceName_="#SERVICE_NAME#";
|
||||
}
|
||||
bool #CLIENT_CLASS_NAME#::Connect(const std::string addrname)
|
||||
{
|
||||
if (unixSocketClient_!=nullptr) {
|
||||
return false;
|
||||
}
|
||||
unixSocketClient_ = std::make_shared<UnixSocketClient>();
|
||||
if (!unixSocketClient_->Connect(addrname, *this)) {
|
||||
unixSocketClient_=nullptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#CLIENT_SEND_REQUEST_PROC_FUNC#
|
||||
|
||||
#CLIENT_SEND_PROTOCOL_PROC_FUNC#
|
||||
bool #CLIENT_CLASS_NAME#::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size)
|
||||
{
|
||||
switch (pnum) {
|
||||
#CLIENT_PROTOCOL_PROC#
|
||||
}
|
||||
if (waitingFor==pnum) {
|
||||
waitingFor=-1;
|
||||
mWait_.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
)";
|
||||
|
||||
std::string SwapName(std::string s)
|
||||
{
|
||||
std::string ret = "";
|
||||
bool b = true;
|
||||
for (size_t i = 0; i < s.length(); i++) {
|
||||
char c = s[i];
|
||||
if (c == '_') {
|
||||
b = true;
|
||||
} else if (b && c >= 'a' && c <= 'z') {
|
||||
ret += (c + 'A' - 'a');
|
||||
b = false;
|
||||
} else {
|
||||
ret += c;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::string ReplaceStr(const std::string& base, const std::string& _from, const std::string& _to)
|
||||
{
|
||||
std::string ret = base;
|
||||
while (true) {
|
||||
size_t pos = ret.find(_from, 0);
|
||||
if (pos == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
ret.replace(pos, _from.length(), _to);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string IpcGeneratorImpl::SetNames(std::string fileName, std::string packageName)
|
||||
{
|
||||
fileName_ = fileName;
|
||||
packageName_ = packageName + "::";
|
||||
headFileName_ = "";
|
||||
|
||||
for (size_t i = 0; i < fileName.length(); i++) {
|
||||
if (fileName.c_str()[i] == '.') {
|
||||
break;
|
||||
}
|
||||
headFileName_ += fileName.c_str()[i];
|
||||
}
|
||||
baseName_ = SwapName(headFileName_);
|
||||
|
||||
serviceCount_ = 0;
|
||||
|
||||
serviceList_.clear();
|
||||
enumMessageDict_.clear();
|
||||
|
||||
return headFileName_;
|
||||
}
|
||||
|
||||
bool IpcGeneratorImpl::AddService(std::string serviceName)
|
||||
{
|
||||
for (int i = 0; i < serviceCount_; i++) {
|
||||
if (serviceList_[i].serviceName_ == serviceName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
serviceList_[serviceCount_].serviceName_ = serviceName;
|
||||
serviceCount_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcGeneratorImpl::AddServiceMethod(std::string serviceName,
|
||||
std::string methodName,
|
||||
std::string requestName,
|
||||
std::string responseName)
|
||||
{
|
||||
for (int i = 0; i < serviceCount_; i++) {
|
||||
if (serviceList_[i].serviceName_ == serviceName) {
|
||||
return serviceList_[i].AddMethod(methodName, requestName, responseName);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IpcGeneratorImpl::GenerateHeader(std::string& header_str)
|
||||
{
|
||||
for (int i = 0; i < serviceCount_; i++) {
|
||||
std::string server_class_name = serviceList_[i].serviceName_ + "Server";
|
||||
header_str = ReplaceStr(header_str, "#SERVICE_CLASS_NAME#", server_class_name);
|
||||
|
||||
std::string tmp1 = "";
|
||||
std::string tmp2 = "";
|
||||
for (int j = 0; j < serviceList_[i].methodCount_; j++) {
|
||||
tmp1 += "\tvirtual bool " + serviceList_[i].methodList_[j] + "(SocketContext &context," + packageName_ +
|
||||
serviceList_[i].requestList_[j] + " &request," + packageName_ + serviceList_[i].responseList_[j] +
|
||||
" &response);\n";
|
||||
|
||||
tmp2 += "\tbool SendResponse" + serviceList_[i].responseList_[j] + "(SocketContext &context," +
|
||||
packageName_ + serviceList_[i].responseList_[j] + " &response);\n";
|
||||
}
|
||||
tmp1 += "\n" + tmp2;
|
||||
header_str = ReplaceStr(header_str, "#RESPONSE_DEFINE#", tmp1);
|
||||
|
||||
std::string client_class_name = serviceList_[i].serviceName_ + "Client";
|
||||
header_str = ReplaceStr(header_str, "#CLIENT_CLASS_NAME#", client_class_name);
|
||||
|
||||
tmp1 = "";
|
||||
for (int j = 0; j < serviceList_[i].methodCount_; j++) {
|
||||
tmp1 += "\tbool " + serviceList_[i].methodList_[j] + "(" + packageName_ + serviceList_[i].requestList_[j];
|
||||
tmp1 += " &request," + packageName_ + serviceList_[i].responseList_[j];
|
||||
tmp1 += " &response,uint32_t timeout_ms=5000);\n";
|
||||
tmp1 += "\tbool " + serviceList_[i].methodList_[j] + "(" + packageName_ + serviceList_[i].requestList_[j];
|
||||
tmp1 += " &request);\n";
|
||||
}
|
||||
tmp1 += "\n";
|
||||
for (int j = 0; j < serviceList_[i].methodCount_; j++) {
|
||||
tmp1 += "\tvirtual bool On" + serviceList_[i].responseList_[j] + "(SocketContext &context," + packageName_;
|
||||
tmp1 += serviceList_[i].responseList_[j] + " &response);\n";
|
||||
}
|
||||
|
||||
header_str = ReplaceStr(header_str, "#VIRTUAL_RESPONSE_FUNC#", tmp1);
|
||||
}
|
||||
}
|
||||
|
||||
std::string IpcGeneratorImpl::GenHeader()
|
||||
{
|
||||
std::string header_str = BASE_HEADER_STRING;
|
||||
std::string tmp1, tmp2;
|
||||
header_str = ReplaceStr(header_str, "#HEAD_FILE_NAME#", headFileName_);
|
||||
|
||||
if (serviceCount_ > 0) {
|
||||
tmp1 = "enum {\n";
|
||||
for (int i = 0; i < serviceCount_; i++) {
|
||||
for (int j = 0; j < serviceList_[i].methodCount_; j++) {
|
||||
tmp1 += "\tIpcProtocol" + baseName_ + serviceList_[i].requestList_[j];
|
||||
tmp1 += "=" + std::to_string(j * 2) + ",\n";
|
||||
tmp1 += "\tIpcProtocol" + baseName_ + serviceList_[i].responseList_[j];
|
||||
tmp1 += "=" + std::to_string(j * 2 + 1) + ",\n";
|
||||
}
|
||||
}
|
||||
tmp1 += "};";
|
||||
} else {
|
||||
tmp1 = "";
|
||||
}
|
||||
header_str = ReplaceStr(header_str, "#PROTOCOL_ENUM#", tmp1);
|
||||
|
||||
GenerateHeader(header_str);
|
||||
header_str = ReplaceStr(header_str, "\t", " ");
|
||||
return header_str;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const std::string SEND_RESPONSE_IMPL_STRING = R"(
|
||||
bool #SERVER_CLASS_NAME#::SendResponse#RESPONSE_NAME#(SocketContext &context,
|
||||
#PACKAGE_NAME##RESPONSE_NAME# &response) {
|
||||
context.SendProtobuf(#ENUM_STR#, response);
|
||||
return false;
|
||||
}
|
||||
)";
|
||||
}
|
||||
std::string IpcGeneratorImpl::GenSendResponseImpl(int servicep, const std::string& server_class_name)
|
||||
{
|
||||
std::string ret = "";
|
||||
for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
|
||||
std::string enum_str = "IpcProtocol" + baseName_ + serviceList_[servicep].responseList_[j];
|
||||
std::string tmp = ReplaceStr(SEND_RESPONSE_IMPL_STRING, "#SERVER_CLASS_NAME#", server_class_name);
|
||||
tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
tmp = ReplaceStr(tmp, "#ENUM_STR#", enum_str);
|
||||
ret += tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
namespace {
|
||||
const std::string ON_RESPONSE_IMPL_STRING = R"(
|
||||
bool #CLIENT_CLASS_NAME#::On#RESPONSE_NAME#(SocketContext &context, #PACKAGE_NAME##RESPONSE_NAME# &response) {
|
||||
return false;
|
||||
}
|
||||
)";
|
||||
}
|
||||
std::string IpcGeneratorImpl::GenOnResponseImpl(int servicep, const std::string& client_class_name)
|
||||
{
|
||||
std::string ret = "";
|
||||
for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
|
||||
std::string tmp = ReplaceStr(ON_RESPONSE_IMPL_STRING, "#CLIENT_CLASS_NAME#", client_class_name);
|
||||
tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
ret += tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
namespace {
|
||||
const std::string SERVICE_CALL_IMPL_STRING = R"(
|
||||
bool #SERVER_CLASS_NAME#::#METHOD_NAME#(SocketContext &context,
|
||||
#PACKAGE_NAME##REQUEST_NAME# &request,
|
||||
#PACKAGE_NAME##RESPONSE_NAME# &response){
|
||||
return false;
|
||||
}
|
||||
)";
|
||||
}
|
||||
std::string IpcGeneratorImpl::GenServiceCallImpl(int servicep, const std::string& server_class_name)
|
||||
{
|
||||
std::string ret = "";
|
||||
for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
|
||||
std::string tmp = ReplaceStr(SERVICE_CALL_IMPL_STRING, "#SERVER_CLASS_NAME#", server_class_name);
|
||||
tmp = ReplaceStr(tmp, "#SERVER_CLASS_NAME#", server_class_name);
|
||||
tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
ret += tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
namespace {
|
||||
const std::string CLIENT_PROC_IMPL_STRING = R"(
|
||||
case IpcProtocol#BASE_NAME##REQUEST_NAME#:{
|
||||
#PACKAGE_NAME##REQUEST_NAME# request;
|
||||
#PACKAGE_NAME##RESPONSE_NAME# response;
|
||||
request.ParseFromArray(buf, size);
|
||||
if (#METHOD_NAME#(context, request, response)) {
|
||||
context.SendProtobuf(IpcProtocol#BASE_NAME##RESPONSE_NAME#, response);
|
||||
}
|
||||
}
|
||||
break;
|
||||
)";
|
||||
}
|
||||
std::string IpcGeneratorImpl::GenClientProcImpl(int servicep)
|
||||
{
|
||||
std::string ret = "";
|
||||
for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
|
||||
std::string tmp = ReplaceStr(CLIENT_PROC_IMPL_STRING, "#BASE_NAME#", baseName_);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
ret += tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
namespace {
|
||||
const std::string CLIENT_REQUEST_IMPL_STRING = R"(
|
||||
bool #CLIENT_CLASS_NAME#::#METHOD_NAME#(#PACKAGE_NAME##REQUEST_NAME# &request,
|
||||
#PACKAGE_NAME##RESPONSE_NAME# &response,
|
||||
uint32_t timeout_ms)
|
||||
{
|
||||
mWait_.lock();
|
||||
if (timeout_ms<=0) {
|
||||
timeout_ms=WAIT_FOR_EVER;
|
||||
}
|
||||
waitingFor=IpcProtocol#BASE_NAME##RESPONSE_NAME#;
|
||||
presponse=&response;
|
||||
unixSocketClient_->SendProtobuf(IpcProtocol#BASE_NAME##REQUEST_NAME#, request);
|
||||
|
||||
if (mWait_.try_lock_for(std::chrono::milliseconds(timeout_ms))) {
|
||||
mWait_.unlock();
|
||||
return true;
|
||||
}
|
||||
waitingFor=-1;
|
||||
mWait_.unlock();
|
||||
return false;
|
||||
}
|
||||
bool #CLIENT_CLASS_NAME#::#METHOD_NAME#(#PACKAGE_NAME##REQUEST_NAME# &request)
|
||||
{
|
||||
unixSocketClient_->SendProtobuf(IpcProtocol#BASE_NAME##REQUEST_NAME#, request);
|
||||
return true;
|
||||
}
|
||||
)";
|
||||
}
|
||||
std::string IpcGeneratorImpl::GenClientRequestImpl(int servicep, const std::string& client_class_name)
|
||||
{
|
||||
std::string ret = "";
|
||||
for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
|
||||
std::string tmp = ReplaceStr(CLIENT_REQUEST_IMPL_STRING, "#CLIENT_CLASS_NAME#", client_class_name);
|
||||
tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#BASE_NAME#", baseName_);
|
||||
ret += tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
namespace {
|
||||
const std::string SERVICE_PROC_IMPL_STRING = R"(
|
||||
case IpcProtocol#BASE_NAME##RESPONSE_NAME#:
|
||||
{
|
||||
if (waitingFor==pnum) {
|
||||
presponse->ParseFromArray(buf, size);
|
||||
}
|
||||
else {
|
||||
#PACKAGE_NAME##RESPONSE_NAME# response#NUM#;
|
||||
response#NUM#.ParseFromArray(buf, size);
|
||||
On#RESPONSE_NAME#(context, response#NUM#);
|
||||
}
|
||||
}
|
||||
break;
|
||||
)";
|
||||
}
|
||||
std::string IpcGeneratorImpl::GenServiceProcImpl(int servicep)
|
||||
{
|
||||
std::string ret = "";
|
||||
for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
|
||||
std::string tmp = ReplaceStr(SERVICE_PROC_IMPL_STRING, "#BASE_NAME#", baseName_);
|
||||
tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
|
||||
tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
|
||||
tmp = ReplaceStr(tmp, "#NUM#", std::to_string(j + 1));
|
||||
|
||||
ret += tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string IpcGeneratorImpl::GenSource()
|
||||
{
|
||||
std::string source_str = BASE_SOURCE_STRING;
|
||||
|
||||
source_str = ReplaceStr(source_str, "#HEAD_FILE_NAME#", headFileName_);
|
||||
|
||||
for (int i = 0; i < serviceCount_; i++) {
|
||||
std::string server_class_name = serviceList_[i].serviceName_ + "Server";
|
||||
source_str = ReplaceStr(source_str, "#SERVICE_CLASS_NAME#", server_class_name);
|
||||
source_str = ReplaceStr(source_str, "#SERVICE_NAME#", serviceList_[i].serviceName_);
|
||||
std::string client_class_name = serviceList_[i].serviceName_ + "Client";
|
||||
source_str = ReplaceStr(source_str, "#CLIENT_CLASS_NAME#", client_class_name);
|
||||
|
||||
source_str = ReplaceStr(source_str, "#RESPONSE_IMPLEMENT#", GenSendResponseImpl(i, server_class_name));
|
||||
source_str = ReplaceStr(source_str, "#CLIENT_SEND_REQUEST_PROC_FUNC#", GenOnResponseImpl(i, client_class_name));
|
||||
|
||||
source_str = ReplaceStr(source_str, "#SERVICE_PROTOCOL_PROC_FUNC#", GenServiceCallImpl(i, server_class_name));
|
||||
source_str = ReplaceStr(source_str, "#SERVICE_PROTOCOL_PROC#", GenClientProcImpl(i));
|
||||
source_str = ReplaceStr(source_str, "#SERVICE_NAME#", serviceList_[i].serviceName_);
|
||||
|
||||
source_str = ReplaceStr(source_str, "#CLIENT_PROTOCOL_PROC#", GenServiceProcImpl(i));
|
||||
source_str =
|
||||
ReplaceStr(source_str, "#CLIENT_SEND_PROTOCOL_PROC_FUNC#", GenClientRequestImpl(i, client_class_name));
|
||||
}
|
||||
|
||||
source_str = ReplaceStr(source_str, "\t", " ");
|
||||
return source_str;
|
||||
}
|
23
device/services/ipc/src/main.cpp
Executable file
23
device/services/ipc/src/main.cpp
Executable file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ipc_generator.h"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
IpcGenerator generator;
|
||||
return google::protobuf::compiler::PluginMain(argc, argv, &generator);
|
||||
}
|
79
device/services/ipc/src/service_entry.cpp
Executable file
79
device/services/ipc/src/service_entry.cpp
Executable file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "service_entry.h"
|
||||
#include "logging.h"
|
||||
#include "service_base.h"
|
||||
#include "unix_socket_server.h"
|
||||
|
||||
ServiceEntry::ServiceEntry()
|
||||
{
|
||||
unixSocketServer_ = nullptr;
|
||||
}
|
||||
ServiceEntry::~ServiceEntry() {}
|
||||
bool ServiceEntry::StartServer(const std::string& addrname)
|
||||
{
|
||||
CHECK_TRUE(unixSocketServer_ == nullptr, false, "Servier Already Started");
|
||||
|
||||
auto server = std::make_shared<UnixSocketServer>();
|
||||
|
||||
CHECK_TRUE(server->StartServer(addrname, *this), false, "StartServer FAIL");
|
||||
|
||||
unixSocketServer_ = server;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceEntry::RegisterService(ServiceBase& psb)
|
||||
{
|
||||
CHECK_TRUE(serviceMap_.find(psb.serviceName_) == serviceMap_.end(), false, "RegisterService FAIL");
|
||||
serviceMap_[psb.serviceName_] = &psb;
|
||||
return true;
|
||||
}
|
||||
const ServiceBase* ServiceEntry::FindServiceByName(const std::string& service_name)
|
||||
{
|
||||
CHECK_TRUE(serviceMap_.find(service_name) != serviceMap_.end(), nullptr, "FindServiceByName FAIL %s",
|
||||
service_name.c_str());
|
||||
|
||||
return serviceMap_[service_name];
|
||||
}
|
||||
|
||||
namespace {
|
||||
const int MS_PER_S = 1000;
|
||||
const int US_PER_S = 1000000;
|
||||
const int NS_PER_US = 1000;
|
||||
const int NS_PER_S = 1000000000;
|
||||
const int NS_PER_MS = 1000000;
|
||||
} // namespace
|
||||
|
||||
uint64_t GetTimeMS()
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_BOOTTIME, &ts);
|
||||
return ts.tv_sec * MS_PER_S + ts.tv_nsec / NS_PER_MS;
|
||||
}
|
||||
|
||||
uint64_t GetTimeUS()
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_BOOTTIME, &ts);
|
||||
return ts.tv_sec * US_PER_S + ts.tv_nsec / NS_PER_US;
|
||||
}
|
||||
|
||||
uint64_t GetTimeNS()
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_BOOTTIME, &ts);
|
||||
return ts.tv_sec * NS_PER_S + ts.tv_nsec;
|
||||
}
|
214
device/services/ipc/src/socket_context.cpp
Executable file
214
device/services/ipc/src/socket_context.cpp
Executable file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "socket_context.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include "logging.h"
|
||||
#include "securec.h"
|
||||
#include "service_base.h"
|
||||
#include "service_entry.h"
|
||||
|
||||
namespace {
|
||||
const int PROTO_SIZE_MAX = 1024 * 1024;
|
||||
const int MEMORY_BLOCK_UNIT = 4096;
|
||||
} // namespace
|
||||
|
||||
SocketContext::SocketContext()
|
||||
{
|
||||
socketHandle_ = -1;
|
||||
clientState_ = CLIENT_STAT_WORKING;
|
||||
lastProcMS_ = 0;
|
||||
serviceBase_ = nullptr;
|
||||
}
|
||||
|
||||
SocketContext::~SocketContext()
|
||||
{
|
||||
if (socketHandle_ >= 0) {
|
||||
close(socketHandle_);
|
||||
socketHandle_ = -1;
|
||||
}
|
||||
if (recvThread_.joinable()) {
|
||||
recvThread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
int SocketContext::RawProtocolProc(uint32_t pnum, const int8_t* buf, const uint32_t size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ReceiveData(int sock, uint8_t* databuf, uint32_t size)
|
||||
{
|
||||
uint32_t p = 0;
|
||||
if (sock < 0) {
|
||||
return false;
|
||||
}
|
||||
while (p < size) {
|
||||
int ret = recv(sock, &databuf[p], size - p, 0);
|
||||
if (ret <= 0) {
|
||||
if (ret == -1 && errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
p += ret;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void* SocketContext::UnixSocketRecv(void* pp)
|
||||
{
|
||||
pthread_setname_np(pthread_self(), "UnixSocketRecv");
|
||||
|
||||
uint32_t bufferSize = MEMORY_BLOCK_UNIT;
|
||||
|
||||
SocketContext* pssr = (SocketContext*)pp;
|
||||
std::vector<unsigned char> buf(bufferSize);
|
||||
|
||||
struct ProtocolHead* pph = (struct ProtocolHead*)buf.data();
|
||||
uint32_t head_size = sizeof(struct ProtocolHead);
|
||||
|
||||
CHECK_TRUE(pssr->socketHandle_ != -1, nullptr, "UnixSocketRecv pssr->socketHandle_ ==-1");
|
||||
struct timeval timeout = {1, 0};
|
||||
CHECK_TRUE(setsockopt(pssr->socketHandle_, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0, nullptr,
|
||||
"setsockopt %s", strerror(errno));
|
||||
while (pssr->socketHandle_ >= 0) {
|
||||
if (!ReceiveData(pssr->socketHandle_, buf.data(), head_size)) {
|
||||
HILOG_DEBUG(LOG_CORE, "====== IPC LOST CONNECT ======");
|
||||
break;
|
||||
}
|
||||
if (pph->protoSize > bufferSize) {
|
||||
if (pph->protoSize > PROTO_SIZE_MAX) {
|
||||
HILOG_ERROR(LOG_CORE, "buffer size out of range %d/%d", pph->protoSize, PROTO_SIZE_MAX);
|
||||
break;
|
||||
}
|
||||
bufferSize = (pph->protoSize / MEMORY_BLOCK_UNIT + 1) * MEMORY_BLOCK_UNIT;
|
||||
buf.resize(bufferSize);
|
||||
pph = (struct ProtocolHead*)buf.data();
|
||||
}
|
||||
|
||||
if (!ReceiveData(pssr->socketHandle_, buf.data() + head_size, pph->protoSize - head_size)) {
|
||||
HILOG_DEBUG(LOG_CORE, "====== IPC LOST CONNECT ======");
|
||||
break;
|
||||
}
|
||||
switch (pph->protoType & PROTOCOL_TYPE_FILTER) {
|
||||
case PROTOCOL_TYPE_RAW:
|
||||
pssr->RawProtocolProc(pph->protoType & (~PROTOCOL_TYPE_FILTER), pph->datas, pph->protoSize - head_size);
|
||||
break;
|
||||
case PROTOCOL_TYPE_PROTOBUF:
|
||||
if (pssr->serviceBase_ != nullptr) {
|
||||
pssr->serviceBase_->ProtocolProc(*pssr, pph->protoType & (~PROTOCOL_TYPE_FILTER), pph->datas,
|
||||
pph->protoSize - head_size);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
HILOG_ERROR(LOG_CORE, "unknown protocol %d", pph->protoType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pssr->clientState_ = CLIENT_STAT_THREAD_EXITED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SocketContext::CreateRecvThread()
|
||||
{
|
||||
recvThread_ = std::thread(&SocketContext::UnixSocketRecv, this);
|
||||
CHECK_TRUE(recvThread_.get_id() != std::thread::id(), false, "CreateRecvThread FAIL");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketContext::SendRaw(uint32_t pnum, const int8_t* data, uint32_t size, int sockfd)
|
||||
{
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (sockfd == -1) {
|
||||
sockfd = socketHandle_;
|
||||
}
|
||||
struct ProtocolHead phead;
|
||||
phead.protoType = PROTOCOL_TYPE_RAW | pnum;
|
||||
phead.protoSize = size + sizeof(struct ProtocolHead);
|
||||
CHECK_TRUE(send(sockfd, reinterpret_cast<int8_t*>(&phead), sizeof(struct ProtocolHead), 0) != -1, false,
|
||||
"SendRaw Send Head ERR :%s", strerror(errno));
|
||||
|
||||
CHECK_TRUE(send(sockfd, data, size, 0) != -1, false, "SendRaw Send Data ERR : %s", strerror(errno));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketContext::SendProtobuf(uint32_t pnum, google::protobuf::Message& pmsg)
|
||||
{
|
||||
int size = pmsg.ByteSizeLong();
|
||||
int8_t* data = reinterpret_cast<int8_t*>(malloc(size));
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
pmsg.SerializeToArray(data, size);
|
||||
struct ProtocolHead phead;
|
||||
phead.protoType = PROTOCOL_TYPE_PROTOBUF | pnum;
|
||||
phead.protoSize = size + sizeof(struct ProtocolHead);
|
||||
send(socketHandle_, reinterpret_cast<int8_t*>(&phead), sizeof(struct ProtocolHead), 0);
|
||||
send(socketHandle_, data, size, 0);
|
||||
|
||||
free(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketContext::SendFileDescriptor(int fd)
|
||||
{
|
||||
struct msghdr msg = {0};
|
||||
struct cmsghdr* cmsg = nullptr;
|
||||
char buf[CMSG_SPACE(1 * sizeof(int))], data;
|
||||
if (memset_s(buf, sizeof(buf), 0, sizeof(buf)) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "memset_s error!");
|
||||
}
|
||||
struct iovec io = {.iov_base = &data, .iov_len = 1};
|
||||
msg.msg_iov = &io;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = buf;
|
||||
msg.msg_controllen = sizeof(buf);
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * 1);
|
||||
if (memcpy_s(CMSG_DATA(cmsg), 1 * sizeof(int), &fd, 1 * sizeof(int)) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "memcpy_s error");
|
||||
}
|
||||
|
||||
CHECK_TRUE(sendmsg(socketHandle_, &msg, 0) != -1, false, "SendFileDescriptor FAIL");
|
||||
return true;
|
||||
}
|
||||
|
||||
int SocketContext::ReceiveFileDiscriptor()
|
||||
{
|
||||
struct msghdr msg = {0};
|
||||
struct cmsghdr* cmsg = nullptr;
|
||||
char buf[CMSG_SPACE(1 * sizeof(int))], data;
|
||||
struct iovec io = {.iov_base = &data, .iov_len = 1};
|
||||
msg.msg_iov = &io;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = buf;
|
||||
msg.msg_controllen = sizeof(buf);
|
||||
|
||||
CHECK_TRUE(recvmsg(socketHandle_, &msg, 0) != -1, -1, "ReceiveFileDiscriptor FAIL");
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
return cmsg ? *(int*)CMSG_DATA(cmsg) : -1;
|
||||
}
|
68
device/services/ipc/src/unix_socket_client.cpp
Executable file
68
device/services/ipc/src/unix_socket_client.cpp
Executable file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "unix_socket_client.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "securec.h"
|
||||
#include "service_base.h"
|
||||
|
||||
UnixSocketClient::UnixSocketClient()
|
||||
{
|
||||
serviceBase_ = nullptr;
|
||||
socketHandle_ = -1;
|
||||
}
|
||||
|
||||
UnixSocketClient::~UnixSocketClient() {}
|
||||
|
||||
bool UnixSocketClient::Connect(const std::string addrname, ServiceBase& serviceBase)
|
||||
{
|
||||
CHECK_TRUE(socketHandle_ == -1, false, "socketHandle_ != -1 Already Connected");
|
||||
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
CHECK_TRUE(sock != -1, false, "Unix Socket Create FAIL");
|
||||
|
||||
struct sockaddr_un addr;
|
||||
if (memset_s(&addr, sizeof(struct sockaddr_un), 0, sizeof(struct sockaddr_un)) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "memset_s error!");
|
||||
}
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (strncpy_s(addr.sun_path, UNIX_PATH_MAX, addrname.c_str(), sizeof(addr.sun_path) - 1) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "strncpy_s error!");
|
||||
}
|
||||
|
||||
CHECK_TRUE(connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) != -1, close(sock) != 0,
|
||||
"Unix Socket Connect FAIL");
|
||||
|
||||
serviceBase_ = &serviceBase;
|
||||
struct RawPointToService rrs;
|
||||
if (strncpy_s(rrs.serviceName_, sizeof(rrs.serviceName_),
|
||||
serviceBase_->serviceName_.c_str(), serviceBase_->serviceName_.size()) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "strncpy_s error!");
|
||||
}
|
||||
rrs.serviceName_[serviceBase_->serviceName_.size()] = 0;
|
||||
CHECK_TRUE(
|
||||
SendRaw(RAW_PROTOCOL_POINTTO_SERVICE, reinterpret_cast<int8_t*>(&rrs), sizeof(struct RawPointToService), sock),
|
||||
close(sock) != 0, "Unix Socket SendRaw FAIL");
|
||||
CHECK_TRUE(CreateRecvThread(), close(sock) != 0, "Unix Socket Create Recv Thread FAIL");
|
||||
socketHandle_ = sock;
|
||||
return true;
|
||||
}
|
116
device/services/ipc/src/unix_socket_server.cpp
Executable file
116
device/services/ipc/src/unix_socket_server.cpp
Executable file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "unix_socket_server.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <pthread.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "client_map.h"
|
||||
#include "logging.h"
|
||||
#include "securec.h"
|
||||
|
||||
UnixSocketServer::UnixSocketServer()
|
||||
{
|
||||
sAddrName_ = "";
|
||||
socketHandle_ = -1;
|
||||
serviceEntry_ = nullptr;
|
||||
}
|
||||
|
||||
UnixSocketServer::~UnixSocketServer()
|
||||
{
|
||||
if (socketHandle_ != 1) {
|
||||
close(socketHandle_);
|
||||
socketHandle_ = -1;
|
||||
unlink(sAddrName_.c_str());
|
||||
}
|
||||
if (acceptThread_.joinable()) {
|
||||
acceptThread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void* UnixSocketServer::UnixSocketAccept(void* p)
|
||||
{
|
||||
if (p == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
pthread_setname_np(pthread_self(), "UnixSocketAccept");
|
||||
|
||||
UnixSocketServer* puss = (UnixSocketServer*)p;
|
||||
if (puss == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
CHECK_TRUE(puss->socketHandle_ != -1, nullptr, "Unix Socket Accept socketHandle_ == -1");
|
||||
int epfd = epoll_create(1);
|
||||
struct epoll_event evt;
|
||||
evt.data.fd = puss->socketHandle_;
|
||||
evt.events = EPOLLIN | EPOLLET;
|
||||
CHECK_TRUE(epoll_ctl(epfd, EPOLL_CTL_ADD, puss->socketHandle_, &evt) != -1, nullptr, "Unix Socket Server Exit");
|
||||
int nfds;
|
||||
while (puss->socketHandle_ != -1) {
|
||||
nfds = epoll_wait(epfd, &evt, 1, 1000); // timeout value set 1000.
|
||||
if (nfds > 0) {
|
||||
int clientSocket = accept(puss->socketHandle_, nullptr, nullptr);
|
||||
HILOG_INFO(LOG_CORE, "Accept A Client %d", clientSocket);
|
||||
ClientMap::GetInstance().PutClientSocket(clientSocket, *puss->serviceEntry_);
|
||||
}
|
||||
}
|
||||
close(epfd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const int UNIX_SOCKET_LISTEN_COUNT = 5;
|
||||
}
|
||||
bool UnixSocketServer::StartServer(const std::string& addrname, ServiceEntry& p)
|
||||
{
|
||||
CHECK_TRUE(socketHandle_ == -1, false, "StartServer FAIL socketHandle_ != -1");
|
||||
|
||||
struct sockaddr_un addr;
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
CHECK_TRUE(sock != -1, false, "StartServer FAIL create socket ERR : %s", strerror(errno));
|
||||
|
||||
if (memset_s(&addr, sizeof(struct sockaddr_un), 0, sizeof(struct sockaddr_un)) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "memset_s error!");
|
||||
}
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (strncpy_s(addr.sun_path, UNIX_PATH_MAX, addrname.c_str(), sizeof(addr.sun_path) - 1) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "strncpy_s error!");
|
||||
}
|
||||
unlink(addrname.c_str());
|
||||
CHECK_TRUE(bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) == 0, close(sock) != 0,
|
||||
"StartServer FAIL bind ERR : %s", strerror(errno));
|
||||
|
||||
CHECK_TRUE(listen(sock, UNIX_SOCKET_LISTEN_COUNT) != -1, close(sock) != 0 && unlink(addrname.c_str()) == 0,
|
||||
"StartServer FAIL listen ERR : %s", strerror(errno));
|
||||
|
||||
socketHandle_ = sock;
|
||||
acceptThread_ = std::thread(&UnixSocketServer::UnixSocketAccept, this);
|
||||
if (acceptThread_.get_id() == std::thread::id()) {
|
||||
close(socketHandle_);
|
||||
unlink(addrname.c_str());
|
||||
HILOG_ERROR(LOG_CORE, "StartServer FAIL pthread_create ERR : %s", strerror(errno));
|
||||
socketHandle_ = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
serviceEntry_ = &p;
|
||||
sAddrName_ = addrname;
|
||||
return true;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user