diff --git a/0052-etmem-correct-example-config-file.patch b/0052-etmem-correct-example-config-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..c65d83f8b9405cac04f2a38ad9e36b48ae24d804 --- /dev/null +++ b/0052-etmem-correct-example-config-file.patch @@ -0,0 +1,38 @@ +From 560e15aea0edc9bf53f33e739b6d430f4fe16150 Mon Sep 17 00:00:00 2001 +From: Kemeng Shi +Date: Tue, 19 Oct 2021 10:36:01 +0800 +Subject: [PATCH 01/33] etmem: correct example config file + +corret value config in cslide task +corret node_pair config in cslide engine + +Signed-off-by: Kemeng Shi +--- + etmem/conf/example_conf.yaml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/etmem/conf/example_conf.yaml b/etmem/conf/example_conf.yaml +index de612f6..61ee68c 100644 +--- a/etmem/conf/example_conf.yaml ++++ b/etmem/conf/example_conf.yaml +@@ -22,7 +22,7 @@ max_threads=1 + [engine] + name=cslide + project=test +-node_pair=2,0;3,1 ++node_pair=0,2;1,3 + hot_threshold=1 + node_mig_quota=1024 + node_hot_reserve=1024 +@@ -32,7 +32,7 @@ project=test + engine=cslide + name=background_cslide + type=pid +-name=23456 ++value=23456 + vm_flags=ht + anon_only=no + ign_host=no +-- +1.8.3.1 + diff --git a/0053-etmem-split-example_conf.yaml.patch b/0053-etmem-split-example_conf.yaml.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6a134a37a41545bf320c894df2064e225bdcdb3 --- /dev/null +++ b/0053-etmem-split-example_conf.yaml.patch @@ -0,0 +1,167 @@ +From 0b40944b0a57393ccedb19b18f5c8307cfd42ffe Mon Sep 17 00:00:00 2001 +From: Kemeng Shi +Date: Tue, 19 Oct 2021 10:43:09 +0800 +Subject: [PATCH 02/33] etmem: split example_conf.yaml + +User can't use example_conf.yaml directly as it contains diffrent +engine configs. Split it into three single engine config and user +can use it directly + +Signed-off-by: Kemeng Shi +--- + etmem/conf/cslide_conf.yaml | 24 ++++++++++++++++++ + etmem/conf/example_conf.yaml | 56 ----------------------------------------- + etmem/conf/slide_conf.yaml | 18 +++++++++++++ + etmem/conf/thirdparty_conf.yaml | 21 ++++++++++++++++ + 4 files changed, 63 insertions(+), 56 deletions(-) + create mode 100644 etmem/conf/cslide_conf.yaml + delete mode 100644 etmem/conf/example_conf.yaml + create mode 100644 etmem/conf/slide_conf.yaml + create mode 100644 etmem/conf/thirdparty_conf.yaml + +diff --git a/etmem/conf/cslide_conf.yaml b/etmem/conf/cslide_conf.yaml +new file mode 100644 +index 0000000..6b6ecc3 +--- /dev/null ++++ b/etmem/conf/cslide_conf.yaml +@@ -0,0 +1,24 @@ ++[project] ++name=test ++loop=1 ++interval=1 ++sleep=1 ++ ++#cslide ++[engine] ++name=cslide ++project=test ++node_pair=0,2;1,3 ++hot_threshold=1 ++node_mig_quota=1024 ++node_hot_reserve=1024 ++ ++[task] ++project=test ++engine=cslide ++name=background_cslide ++type=pid ++value=23456 ++vm_flags=ht ++anon_only=no ++ign_host=no +diff --git a/etmem/conf/example_conf.yaml b/etmem/conf/example_conf.yaml +deleted file mode 100644 +index 61ee68c..0000000 +--- a/etmem/conf/example_conf.yaml ++++ /dev/null +@@ -1,56 +0,0 @@ +-[project] +-name=test +-loop=1 +-interval=1 +-sleep=1 +- +-#slide +-[engine] +-name=slide +-project=test +- +-[task] +-project=test +-engine=slide +-name=background_slide +-type=name +-value=mysql +-T=1 +-max_threads=1 +- +-#cslide +-[engine] +-name=cslide +-project=test +-node_pair=0,2;1,3 +-hot_threshold=1 +-node_mig_quota=1024 +-node_hot_reserve=1024 +- +-[task] +-project=test +-engine=cslide +-name=background_cslide +-type=pid +-value=23456 +-vm_flags=ht +-anon_only=no +-ign_host=no +- +-#thirdparty +-[engine] +-name=thirdparty +-project=test +-eng_name=my_engine +-libname=/usr/lib/etmem_fetch/my_engine.so +-ops_name=my_engine_ops +-engine_private_key=engine_private_value +- +-[task] +-project=test +-engine=my_engine +-name=backgroud_third +-type=pid +-value=12345 +-task_private_key=task_private_value +- +diff --git a/etmem/conf/slide_conf.yaml b/etmem/conf/slide_conf.yaml +new file mode 100644 +index 0000000..b99ab50 +--- /dev/null ++++ b/etmem/conf/slide_conf.yaml +@@ -0,0 +1,18 @@ ++[project] ++name=test ++loop=1 ++interval=1 ++sleep=1 ++ ++[engine] ++name=slide ++project=test ++ ++[task] ++project=test ++engine=slide ++name=background_slide ++type=name ++value=mysql ++T=1 ++max_threads=1 +diff --git a/etmem/conf/thirdparty_conf.yaml b/etmem/conf/thirdparty_conf.yaml +new file mode 100644 +index 0000000..1e1e9ac +--- /dev/null ++++ b/etmem/conf/thirdparty_conf.yaml +@@ -0,0 +1,21 @@ ++[project] ++name=test ++loop=1 ++interval=1 ++sleep=1 ++ ++[engine] ++name=thirdparty ++project=test ++eng_name=my_engine ++libname=/usr/lib/etmem_fetch/my_engine.so ++ops_name=my_engine_ops ++engine_private_key=engine_private_value ++ ++[task] ++project=test ++engine=my_engine ++name=backgroud_third ++type=pid ++value=12345 ++task_private_key=task_private_value +-- +1.8.3.1 + diff --git a/0054-add-License-in-memRouter.patch b/0054-add-License-in-memRouter.patch new file mode 100644 index 0000000000000000000000000000000000000000..07d9838fa6e96399eb91a5055fb713ca2526de0c --- /dev/null +++ b/0054-add-License-in-memRouter.patch @@ -0,0 +1,146 @@ +From 4a8a5272e74994a694b88ab516a5331deea25bd2 Mon Sep 17 00:00:00 2001 +From: volcanodragon +Date: Tue, 9 Nov 2021 15:40:17 +0800 +Subject: [PATCH 03/33] add License in memRouter + +--- + memRouter/License/LICENSE | 127 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 127 insertions(+) + create mode 100644 memRouter/License/LICENSE + +diff --git a/memRouter/License/LICENSE b/memRouter/License/LICENSE +new file mode 100644 +index 0000000..0db93af +--- /dev/null ++++ b/memRouter/License/LICENSE +@@ -0,0 +1,127 @@ ++木兰宽松许可证, 第2版 ++ ++ 木兰宽松许可证, 第2版 ++ 2020年1月 http://license.coscl.org.cn/MulanPSL2 ++ ++ ++ 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: ++ ++ 0. 定义 ++ ++ “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 ++ ++ “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 ++ ++ “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 ++ ++ “法人实体”是指提交贡献的机构及其“关联实体”。 ++ ++ “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 ++ ++ 1. 授予版权许可 ++ ++ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 ++ ++ 2. 授予专利许可 ++ ++ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 ++ ++ 3. 无商标许可 ++ ++ “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 ++ ++ 4. 分发限制 ++ ++ 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 ++ ++ 5. 免责声明与责任限制 ++ ++ “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 ++ ++ 6. 语言 ++ “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 ++ ++ 条款结束 ++ ++ 如何将木兰宽松许可证,第2版,应用到您的软件 ++ ++ 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: ++ ++ 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; ++ ++ 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; ++ ++ 3, 请将如下声明文本放入每个源文件的头部注释中。 ++ ++ Copyright (c) [Year] [name of copyright holder] ++ [Software Name] is licensed under Mulan PSL v2. ++ You can use this software according to the terms and conditions of the Mulan PSL v2. ++ You may obtain a copy of Mulan PSL v2 at: ++ http://license.coscl.org.cn/MulanPSL2 ++ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ See the Mulan PSL v2 for more details. ++ ++ ++ Mulan Permissive Software License,Version 2 ++ ++ Mulan Permissive Software License,Version 2 (Mulan PSL v2) ++ January 2020 http://license.coscl.org.cn/MulanPSL2 ++ ++ Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: ++ ++ 0. Definition ++ ++ Software means the program and related documents which are licensed under this License and comprise all Contribution(s). ++ ++ Contribution means the copyrightable work licensed by a particular Contributor under this License. ++ ++ Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. ++ ++ Legal Entity means the entity making a Contribution and all its Affiliates. ++ ++ Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. ++ ++ 1. Grant of Copyright License ++ ++ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. ++ ++ 2. Grant of Patent License ++ ++ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. ++ ++ 3. No Trademark License ++ ++ No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. ++ ++ 4. Distribution Restriction ++ ++ You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. ++ ++ 5. Disclaimer of Warranty and Limitation of Liability ++ ++ THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ++ ++ 6. Language ++ ++ THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. ++ ++ END OF THE TERMS AND CONDITIONS ++ ++ How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software ++ ++ To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: ++ ++ i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; ++ ++ ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; ++ ++ iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. ++ ++ ++ Copyright (c) [Year] [name of copyright holder] ++ [Software Name] is licensed under Mulan PSL v2. ++ You can use this software according to the terms and conditions of the Mulan PSL v2. ++ You may obtain a copy of Mulan PSL v2 at: ++ http://license.coscl.org.cn/MulanPSL2 ++ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ See the Mulan PSL v2 for more details. +-- +1.8.3.1 + diff --git a/0055-add-code-of-testcase-for-etmem-common-function.patch b/0055-add-code-of-testcase-for-etmem-common-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..5209bda1657650b7ffc8597e500cd5ffbb80f1af --- /dev/null +++ b/0055-add-code-of-testcase-for-etmem-common-function.patch @@ -0,0 +1,698 @@ +From e36c5a68a748080a473988c7530786f3f7ac90d3 Mon Sep 17 00:00:00 2001 +From: louhongxiang +Date: Mon, 22 Nov 2021 17:51:33 +0800 +Subject: [PATCH 04/33] add code of testcase for etmem common function. + +--- + etmem/test/CMakeLists.txt | 198 ++++++++++++++++++++++++ + etmem/test/common/test_common.c | 327 ++++++++++++++++++++++++++++++++++++++++ + etmem/test/common/test_common.h | 138 +++++++++++++++++ + 3 files changed, 663 insertions(+) + create mode 100644 etmem/test/CMakeLists.txt + create mode 100644 etmem/test/common/test_common.c + create mode 100644 etmem/test/common/test_common.h + +diff --git a/etmem/test/CMakeLists.txt b/etmem/test/CMakeLists.txt +new file mode 100644 +index 0000000..5bf3477 +--- /dev/null ++++ b/etmem/test/CMakeLists.txt +@@ -0,0 +1,198 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: louhongxiang ++# * Create: 2021-11-19 ++# * Description: CMakefileList for etmem to compile ++# ******************************************************************************/ ++ ++cmake_minimum_required (VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) ++project(etmem) ++ ++EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE ) ++message( STATUS "Architecture: ${ARCHITECTURE}" ) ++ ++set(ETMEMD_SRC_DIR ${PROJECT_SOURCE_DIR}/../src/etmemd_src) ++set(ETMEM_SRC_DIR ${PROJECT_SOURCE_DIR}/../src/etmem_src) ++set(TEST_COMMON_DIR ${PROJECT_SOURCE_DIR}/common) ++set(BUILD_DIR ${PROJECT_SOURCE_DIR}/build) ++ ++set(ETMEMD_SRC ++ ${ETMEMD_SRC_DIR}/etmemd.c ++ ${ETMEMD_SRC_DIR}/etmemd_file.c ++ ${ETMEMD_SRC_DIR}/etmemd_common.c ++ ${ETMEMD_SRC_DIR}/etmemd_rpc.c ++ ${ETMEMD_SRC_DIR}/etmemd_log.c ++ ${ETMEMD_SRC_DIR}/etmemd_project.c ++ ${ETMEMD_SRC_DIR}/etmemd_engine.c ++ ${ETMEMD_SRC_DIR}/etmemd_memdcd.c ++ ${ETMEMD_SRC_DIR}/etmemd_slide.c ++ ${ETMEMD_SRC_DIR}/etmemd_cslide.c ++ ${ETMEMD_SRC_DIR}/etmemd_thirdparty.c ++ ${ETMEMD_SRC_DIR}/etmemd_task.c ++ ${ETMEMD_SRC_DIR}/etmemd_scan.c ++ ${ETMEMD_SRC_DIR}/etmemd_threadpool.c ++ ${ETMEMD_SRC_DIR}/etmemd_threadtimer.c ++ ${ETMEMD_SRC_DIR}/etmemd_pool_adapter.c ++ ${ETMEMD_SRC_DIR}/etmemd_migrate.c) ++ ++set(ETMEM_SRC ++ ${ETMEM_SRC_DIR}/etmem.c ++ ${ETMEM_SRC_DIR}/etmem_project.c ++ ${ETMEM_SRC_DIR}/etmem_obj.c ++ ${ETMEM_SRC_DIR}/etmem_engine.c ++ ${ETMEM_SRC_DIR}/etmem_rpc.c ++ ${ETMEM_SRC_DIR}/etmem_common.c) ++ ++set(ETMEMD_CSLIDE_DEP ++ ${ETMEMD_SRC_DIR}/etmemd.c ++ ${ETMEMD_SRC_DIR}/etmemd_file.c ++ ${ETMEMD_SRC_DIR}/etmemd_common.c ++ ${ETMEMD_SRC_DIR}/etmemd_rpc.c ++ ${ETMEMD_SRC_DIR}/etmemd_log.c ++ ${ETMEMD_SRC_DIR}/etmemd_project.c ++ ${ETMEMD_SRC_DIR}/etmemd_engine.c ++ ${ETMEMD_SRC_DIR}/etmemd_slide.c ++ ${ETMEMD_SRC_DIR}/etmemd_thirdparty.c ++ ${ETMEMD_SRC_DIR}/etmemd_task.c ++ ${ETMEMD_SRC_DIR}/etmemd_scan.c ++ ${ETMEMD_SRC_DIR}/etmemd_threadpool.c ++ ${ETMEMD_SRC_DIR}/etmemd_threadtimer.c ++ ${ETMEMD_SRC_DIR}/etmemd_pool_adapter.c ++ ${ETMEMD_SRC_DIR}/etmemd_migrate.c) ++ ++set(TEST_COMMON_SRC ++ ${TEST_COMMON_DIR}/test_common.c) ++ ++add_library( ++etmemd_shared ++SHARED ++${ETMEMD_SRC}) ++ ++add_library( ++etmem_shared ++SHARED ++${ETMEM_SRC}) ++ ++add_library( ++test_common ++SHARED ++${TEST_COMMON_SRC}) ++ ++add_library( ++cslide_dep ++SHARED ++${ETMEMD_CSLIDE_DEP}) ++ ++add_executable(etmemd ++ ${ETMEMD_SRC}) ++ ++add_executable(etmem ++ ${ETMEM_SRC}) ++ ++set(EXECUTABLE_OUTPUT_PATH ${BUILD_DIR}/bin) ++ ++set(LIBRARY_OUTPUT_PATH ${BUILD_DIR}/lib) ++ ++include(FindPkgConfig) ++pkg_search_module(GLIB2 REQUIRED glib-2.0) ++ ++target_include_directories(etmemd PRIVATE ++ ${PROJECT_SOURCE_DIR}/../inc/etmemd_inc ++ ${GLIB2_INCLUDE_DIRS}) ++ ++target_include_directories(etmemd_shared PRIVATE ++ ${PROJECT_SOURCE_DIR}/../inc/etmemd_inc ++ ${GLIB2_INCLUDE_DIRS}) ++ ++target_include_directories(etmem PRIVATE ++ ${PROJECT_SOURCE_DIR}/../inc/etmem_inc) ++ ++target_include_directories(etmem_shared PRIVATE ++ ${PROJECT_SOURCE_DIR}/../inc/etmem_inc) ++ ++target_include_directories(test_common PRIVATE ++ ${PROJECT_SOURCE_DIR}/../inc/etmemd_inc ++ ${PROJECT_SOURCE_DIR}/COMMON ++ ${GLIB2_INCLUDE_DIRS}) ++ ++target_include_directories(cslide_dep PRIVATE ++ ${PROJECT_SOURCE_DIR}/../inc/etmemd_inc ++ ${GLIB2_INCLUDE_DIRS}) ++ ++if(COVERAGE_ENABLE) ++ message(STATUS "Enable coverage compile option") ++ SET(COVERAGE_OPTION "${COVERAGE_OPTION} -fprofile-arcs -ftest-coverage") ++endif(COVERAGE_ENABLE) ++ ++if(ASAN_ENABLE) ++ message(STATUS "Enable asan compile option") ++ SET(ASAN_OPTIONS "${ASAN_OPTION} -fsanitize=address -fsanitize-recover=address") ++endif(ASAN_ENABLE) ++ ++IF(CMAKE_BUILD_TYPE STREQUAL Debug) ++ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COVERAGE_OPTION} ${ASAN_OPTIONS}") ++ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COVERAGE_OPTION} ${ASAN_OPTIONS}") ++ENDIF() ++ ++# set common compile options ++set(COMMON_COMPILE_OPT -fsigned-char -fno-omit-frame-pointer -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wmissing-declarations -fno-strict-aliasing -Werror -Wformat -Wformat-security -D_GNU_SOURCE -fPIE -pie -fPIC -fstack-protector-strong -fno-common -DNDEBUG -O2 -D_FORTIFY_SOURCE=2 -Wall -Werror -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -pthread -Wno-pointer-sign -Wstrict-prototypes -Wold-style-definition -std=gnu99) ++ ++if (CONFIG_DEBUG STREQUAL "y") ++ SET(COMMON_COMPILE_OPT ${COMMON_COMPILE_OPT} -g) ++endif() ++ ++if( ${ARCHITECTURE} STREQUAL "aarch64") ++ SET(COMMON_COMPILE_OPT ${COMMON_COMPILE_OPT} -march=armv8-a) ++else() ++ SET(COMMON_COMPILE_OPT ${COMMON_COMPILE_OPT} -march=core-avx-i -m64) ++endif() ++ ++# set common share library compile options ++set(SHARE_COMPILE_OPT -ldl -rdynamic) ++ ++# set common link options ++set(COMMON_LINK_OPT "-fPIE -pie -fPIC -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines") ++set(COMMON_LINK_LIB pthread dl rt boundscheck) ++set(SERVER_LINK_LIB numa ${GLIB2_LIBRARIES}) ++ ++# target etmemd ++target_compile_options(etmemd PRIVATE ${COMMON_COMPILE_OPT}) ++set_target_properties(etmemd PROPERTIES LINK_FLAGS ${COMMON_LINK_OPT}) ++target_link_libraries(etmemd PRIVATE ${COMMON_LINK_LIB} ${SERVER_LINK_LIB}) ++ ++# target etmem ++target_compile_options(etmem PRIVATE ${COMMON_COMPILE_OPT}) ++set_target_properties(etmem PROPERTIES LINK_FLAGS ${COMMON_LINK_OPT}) ++target_link_libraries(etmem PRIVATE ${COMMON_LINK_LIB} ${SERVER_LINK_LIB}) ++ ++# target etmemd share ++target_compile_options(etmemd_shared PRIVATE ${COMMON_COMPILE_OPT} ${SHARE_COMPILE_OPT}) ++set_target_properties(etmemd_shared PROPERTIES LINK_FLAGS ${COMMON_LINK_OPT}) ++target_link_libraries(etmemd_shared PRIVATE ${COMMON_LINK_LIB} ${SERVER_LINK_LIB}) ++SET_TARGET_PROPERTIES(etmemd_shared PROPERTIES OUTPUT_NAME "etmemd") ++ ++# target etmem share ++target_compile_options(etmem_shared PRIVATE ${COMMON_COMPILE_OPT} ${SHARE_COMPILE_OPT}) ++set_target_properties(etmem_shared PROPERTIES LINK_FLAGS ${COMMON_LINK_OPT}) ++target_link_libraries(etmem_shared PRIVATE ${COMMON_LINK_LIB}) ++SET_TARGET_PROPERTIES(etmem_shared PROPERTIES OUTPUT_NAME "etmem") ++ ++# target test etmemd share ++target_compile_options(test_common PRIVATE ${COMMON_COMPILE_OPT} ${SHARE_COMPILE_OPT}) ++set_target_properties(test_common PROPERTIES LINK_FLAGS ${COMMON_LINK_OPT}) ++target_link_libraries(test_common PRIVATE ${COMMON_LINK_LIB} ${SERVER_LINK_LIB}) ++SET_TARGET_PROPERTIES(test_common PROPERTIES OUTPUT_NAME "test") ++ ++# target etmemd cslide share ++target_compile_options(cslide_dep PRIVATE ${COMMON_COMPILE_OPT} ${SHARE_COMPILE_OPT}) ++set_target_properties(cslide_dep PROPERTIES LINK_FLAGS ${COMMON_LINK_OPT}) ++target_link_libraries(cslide_dep PRIVATE ${COMMON_LINK_LIB} ${SERVER_LINK_LIB}) ++ +diff --git a/etmem/test/common/test_common.c b/etmem/test/common/test_common.c +new file mode 100644 +index 0000000..4551177 +--- /dev/null ++++ b/etmem/test/common/test_common.c +@@ -0,0 +1,327 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: louhongxiang ++ * Create: 2021-11-19 ++ * Description: This is a header file of the export data structure definition for page. ++ ******************************************************************************/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_project.h" ++ ++#include "test_common.h" ++ ++#define FIRST_COLD_NODE_INDEX 2 ++#define FIRST_HOT_NODE_INDEX 0 ++#define SECOND_COLD_NODE_INDEX 6 ++#define SECOND_HOT_NODE_INDEX 4 ++ ++GKeyFile *load_config(const char *file_name) ++{ ++ GKeyFile *config = NULL; ++ ++ config = g_key_file_new(); ++ CU_ASSERT_PTR_NOT_NULL(config); ++ CU_ASSERT_NOT_EQUAL(g_key_file_load_from_file(config, file_name, G_KEY_FILE_NONE, NULL), FALSE); ++ return config; ++} ++ ++void unload_config(GKeyFile *config) ++{ ++ g_key_file_free(config); ++} ++ ++void construct_proj_file(struct proj_test_param *param) ++{ ++ FILE *file = NULL; ++ ++ file = fopen(param->file_name, "w+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, "[project]\n"), -1); ++ if (param->proj_name != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_NAME, param->proj_name), -1); ++ } ++ if (param->interval != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_INTERVAL, param->interval), -1); ++ } ++ if (param->loop != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_LOOP, param->loop), -1); ++ } ++ if (param->sleep != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SLEEP, param->sleep), -1); ++ } ++ fclose(file); ++} ++ ++GKeyFile *construct_proj_config(struct proj_test_param *param) ++{ ++ construct_proj_file(param); ++ ++ return load_config(param->file_name); ++} ++ ++void destroy_proj_config(GKeyFile *config) ++{ ++ unload_config(config); ++} ++ ++void init_proj_param(struct proj_test_param *param) ++{ ++ param->sleep = "1"; ++ param->interval = "1"; ++ param->loop = "1"; ++ param->file_name = TMP_PROJ_CONFIG; ++ param->proj_name = DEFAULT_PROJ; ++ param->expt = OPT_SUCCESS; ++} ++ ++void do_add_proj_test(struct proj_test_param * param) ++{ ++ GKeyFile *config = NULL; ++ ++ config = construct_proj_config(param); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), param->expt); ++ destroy_proj_config(config); ++} ++ ++void do_rm_proj_test(struct proj_test_param *param) ++{ ++ GKeyFile *config = NULL; ++ ++ config = load_config(param->file_name); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), param->expt); ++ unload_config(config); ++} ++ ++void construct_eng_file(struct eng_test_param *param) ++{ ++ FILE *file = NULL; ++ ++ file = fopen(param->file_name, "w+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, "[engine]\n"), -1); ++ if (param->name != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_NAME, param->name), -1); ++ } ++ if (param->proj != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_PROJ, param->proj), -1); ++ } ++ fclose(file); ++} ++ ++GKeyFile *construct_eng_config(struct eng_test_param *param) ++{ ++ construct_eng_file(param); ++ ++ return load_config(param->file_name); ++} ++ ++void destroy_eng_config(GKeyFile *config) ++{ ++ unload_config(config); ++} ++ ++void init_task_param(struct task_test_param *param, const char *eng) ++{ ++ param->name = DEFAULT_TASK; ++ param->proj = DEFAULT_PROJ; ++ param->eng = eng; ++ param->type = "pid"; ++ param->value = "1"; ++ param->file_name = TMP_TASK_CONFIG; ++} ++ ++void construct_task_file(struct task_test_param *param) ++{ ++ FILE *file = NULL; ++ ++ file = fopen(param->file_name, "w+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, "[task]\n"), -1); ++ if (param->name != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_NAME, param->name), -1); ++ } ++ if (param->proj != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_PROJ, param->name), -1); ++ } ++ if (param->eng != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_ENG, param->name), -1); ++ } ++ if (param->type != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_TYPE, param->name), -1); ++ } ++ if (param->value != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_VALUE, param->name), -1); ++ } ++ fclose(file); ++} ++ ++void init_slide_task(struct slide_task_test_param *param) ++{ ++ init_task_param(¶m->task_param, "slide"); ++ param->max_threads = "1"; ++ param->T = "1"; ++} ++ ++void add_slide_task(struct slide_task_test_param *param) ++{ ++ FILE *file = NULL; ++ const char *file_name = param->task_param.file_name; ++ ++ file = fopen(file_name, "a+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ if (param->max_threads != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_MAX_THREADS, param->max_threads), -1); ++ } ++ if (param->T != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_T, param->T), -1); ++ } ++ fclose(file); ++} ++ ++GKeyFile *construct_slide_task_config(struct slide_task_test_param *param) ++{ ++ struct task_test_param *task_param = ¶m->task_param; ++ ++ construct_task_file(task_param); ++ add_slide_task(param); ++ ++ return load_config(task_param->file_name); ++} ++ ++void destroy_slide_task_config(GKeyFile *config) ++{ ++ unload_config(config); ++} ++ ++void init_slide_eng(struct eng_test_param *param) ++{ ++ param->name = "slide"; ++ param->proj = DEFAULT_PROJ; ++ param->file_name = TMP_ENG_CONFIG; ++} ++ ++static char *get_node_pair(void) ++{ ++ int node_num = numa_num_configured_nodes(); ++ ++ switch (node_num) { ++ case ONE_NODE_PAIR: ++ return "0,1"; ++ case TWO_NODE_PAIR: ++ return "0,2;1,3"; ++ case THREE_NODE_PAIR: ++ return "0,3;1,4;2,5"; ++ default: ++ return NULL; ++ } ++} ++ ++int get_first_cold_node(struct cslide_eng_test_param *param) ++{ ++ return param->node_pair[FIRST_COLD_NODE_INDEX] - '0'; ++} ++ ++int get_first_hot_node(struct cslide_eng_test_param *param) ++{ ++ return param->node_pair[FIRST_HOT_NODE_INDEX] - '0'; ++} ++ ++int get_second_cold_node(struct cslide_eng_test_param *param) ++{ ++ return param->node_pair[SECOND_COLD_NODE_INDEX] - '0'; ++} ++ ++int get_second_hot_node(struct cslide_eng_test_param *param) ++{ ++ return param->node_pair[SECOND_HOT_NODE_INDEX] - '0'; ++} ++ ++void init_cslide_eng(struct cslide_eng_test_param *param) ++{ ++ param->eng_param.name = "cslide"; ++ param->eng_param.proj = DEFAULT_PROJ; ++ param->eng_param.file_name = TMP_ENG_CONFIG; ++ param->node_pair = get_node_pair(); ++ param->hot_threshold = "2"; ++ param->node_mig_quota = "1024"; ++ param->node_hot_reserve = "1024"; ++} ++ ++void add_cslide_eng(struct cslide_eng_test_param *param) ++{ ++ FILE *file = NULL; ++ const char *file_name = param->eng_param.file_name; ++ ++ file = fopen(file_name, "a+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_NODE_PAIR, param->node_pair), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_THRESH, param->hot_threshold), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_QUOTA, param->node_mig_quota), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_RESV, param->node_hot_reserve), -1); ++ fclose(file); ++} ++ ++GKeyFile *construct_cslide_eng_config(struct cslide_eng_test_param *param) ++{ ++ struct eng_test_param *eng_param = ¶m->eng_param; ++ ++ construct_eng_file(eng_param); ++ add_cslide_eng(param); ++ ++ return load_config(eng_param->file_name); ++} ++ ++void destroy_cslide_eng_config(GKeyFile *config) ++{ ++ unload_config(config); ++} ++ ++void init_cslide_task(struct cslide_task_test_param *param) ++{ ++ init_task_param(¶m->task_param, "cslide"); ++ param->vm_flags = "ht"; ++ param->anon_only = "no"; ++ param->ign_host = "yes"; ++} ++ ++void add_cslide_task(struct cslide_task_test_param *param) ++{ ++ FILE *file = NULL; ++ const char *file_name = param->task_param.file_name; ++ ++ file = fopen(file_name, "a+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_VM_FLAGS, param->vm_flags), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_ANON_ONLY, param->anon_only), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_IGN_HOST, param->ign_host), -1); ++ fclose(file); ++} ++ ++GKeyFile *construct_cslide_task_config(struct cslide_task_test_param *param) ++{ ++ struct task_test_param *task_param = ¶m->task_param; ++ ++ construct_task_file(task_param); ++ add_cslide_task(param); ++ ++ return load_config(task_param->file_name); ++} ++ ++void destroy_cslide_task_config(GKeyFile *config) ++{ ++ unload_config(config); ++} +diff --git a/etmem/test/common/test_common.h b/etmem/test/common/test_common.h +new file mode 100644 +index 0000000..009c458 +--- /dev/null ++++ b/etmem/test/common/test_common.h +@@ -0,0 +1,138 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: louhongxiang ++ * Create: 2021-11-19 ++ * Description: This is a header file of the export data structure definition for page. ++ ******************************************************************************/ ++ ++#ifndef TEST_COMMON_H ++#define TEST_COMMON_H ++ ++#include ++ ++#include "etmemd_project.h" ++ ++#define CONFIG_NAME "name=%s\n" ++#define CONFIG_INTERVAL "interval=%s\n" ++#define CONFIG_LOOP "loop=%s\n" ++#define CONFIG_SLEEP "sleep=%s\n" ++#define TMP_PROJ_CONFIG "proj_tmp.config" ++#define DEFAULT_PROJ "default_proj" ++ ++#define CONFIG_PROJ "project=%s\n" ++#define TMP_ENG_CONFIG "eng_tmp.config" ++ ++#define CONFIG_ENG "engine=%s\n" ++#define CONFIG_TYPE "type=%s\n" ++#define CONFIG_VALUE "value=%s\n" ++#define TMP_TASK_CONFIG "task_tmp.config" ++#define DEFAULT_TASK "default_task" ++ ++#define CONFIG_MAX_THREADS "max_threads=%s\n" ++#define CONFIG_T "T=%s\n" ++ ++#define CONFIG_NODE_PAIR "node_pair=%s\n" ++#define CONFIG_THRESH "hot_threshold=%s\n" ++#define CONFIG_QUOTA "node_mig_quota=%s\n" ++#define CONFIG_RESV "node_hot_reserve=%s\n" ++ ++#define CONFIG_VM_FLAGS "vm_flags=%s\n" ++#define CONFIG_ANON_ONLY "anon_only=%s\n" ++#define CONFIG_IGN_HOST "igno_host=%s\n" ++ ++#define ONE_NODE_PAIR 2 ++#define TWO_NODE_PAIR 4 ++#define THREE_NODE_PAIR 5 ++ ++ ++struct proj_test_param { ++ const char *sleep; ++ const char *interval; ++ const char *loop; ++ const char *proj_name; ++ const char *file_name; ++ enum opt_result expt; ++}; ++ ++struct eng_test_param { ++ const char *name; ++ const char *proj; ++ const char *file_name; ++}; ++ ++struct task_test_param { ++ const char *name; ++ const char *proj; ++ const char *eng; ++ const char *type; ++ const char *value; ++ const char *file_name; ++}; ++ ++struct slide_task_test_param { ++ struct task_test_param task_param; ++ const char *max_threads; ++ const char *T; ++}; ++ ++struct cslide_eng_test_param { ++ struct eng_test_param eng_param; ++ const char *node_pair; ++ const char *hot_threshold; ++ const char *node_mig_quota; ++ const char *node_hot_reserve; ++}; ++ ++struct cslide_task_test_param { ++ struct task_test_param task_param; ++ const char *vm_flags; ++ const char *anon_only; ++ const char *ign_host; ++}; ++ ++GKeyFile *load_config(const char *file_name); ++void unload_config(GKeyFile *config); ++ ++void construct_proj_file(struct proj_test_param *param); ++GKeyFile *construct_proj_config(struct proj_test_param *param); ++void destroy_proj_config(GKeyFile *config); ++void init_proj_param(struct proj_test_param *param); ++void do_add_proj_test(struct proj_test_param *param); ++void do_rm_proj_test(struct proj_test_param *param); ++ ++void construct_eng_file(struct eng_test_param *param); ++GKeyFile *construct_eng_config(struct eng_test_param *param); ++void destroy_eng_config(GKeyFile *config); ++ ++void init_task_param(struct task_test_param *param, const char *eng); ++void construct_task_file(struct task_test_param *param); ++ ++void init_slide_task(struct slide_task_test_param *param); ++void add_slide_task(struct slide_task_test_param *param); ++GKeyFile *construct_slide_task_config(struct slide_task_test_param *param); ++void destroy_slide_task_config(GKeyFile *config); ++void init_slide_eng(struct eng_test_param *param); ++ ++void init_cslide_eng(struct cslide_eng_test_param *param); ++void add_cslide_eng(struct cslide_eng_test_param *param); ++GKeyFile *construct_cslide_eng_config(struct cslide_eng_test_param *param); ++void destroy_cslide_eng_config(GKeyFile *config); ++ ++int get_first_cold_node(struct cslide_eng_test_param *param); ++int get_first_hot_node(struct cslide_eng_test_param *param); ++int get_second_cold_node(struct cslide_eng_test_param *param); ++int get_second_hot_node(struct cslide_eng_test_param *param); ++ ++void init_cslide_task(struct cslide_task_test_param *param); ++void add_cslide_task(struct cslide_task_test_param *param); ++GKeyFile *construct_cslide_task_config(struct cslide_task_test_param *param); ++void destroy_cslide_task_config(GKeyFile *config); ++#endif +-- +1.8.3.1 + diff --git a/0056-add-code-of-testcase-for-etmem-project-function.patch b/0056-add-code-of-testcase-for-etmem-project-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..814c3d2826951ee07672321d76d9c0b905f1c1c3 --- /dev/null +++ b/0056-add-code-of-testcase-for-etmem-project-function.patch @@ -0,0 +1,523 @@ +From f63083aff0d1d305079d9f0c47717faa512361f8 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Tue, 30 Nov 2021 09:42:50 +0800 +Subject: [PATCH 05/33] add code of testcase for etmem project function + +--- + etmem/test/project/CMakeLists.txt | 28 ++ + etmem/test/project/etmem_project_ops_llt.c | 468 +++++++++++++++++++++++++++++ + 2 files changed, 496 insertions(+) + create mode 100644 etmem/test/project/CMakeLists.txt + create mode 100644 etmem/test/project/etmem_project_ops_llt.c + +diff --git a/etmem/test/project/CMakeLists.txt b/etmem/test/project/CMakeLists.txt +new file mode 100644 +index 0000000..70cd530 +--- /dev/null ++++ b/etmem/test/project/CMakeLists.txt +@@ -0,0 +1,28 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-11-29 ++# * Description: CMakefileList for etmem_project_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(../common) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_project_ops_llt) ++ ++add_executable(${EXE} ++etmem_project_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so ${BUILD_DIR}/lib/libtest.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/project/etmem_project_ops_llt.c b/etmem/test/project/etmem_project_ops_llt.c +new file mode 100644 +index 0000000..edd2330 +--- /dev/null ++++ b/etmem/test/project/etmem_project_ops_llt.c +@@ -0,0 +1,468 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-11-29 ++ * Description: This is a source file of the unit test for project-related commands in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "etmemd_project.h" ++#include "etmemd_file.h" ++#include "etmemd_common.h" ++#include "securec.h" ++ ++#include "test_common.h" ++ ++#include ++#include ++#include ++ ++#define PROJECT_ADD_TEST_MAX_NUM 50 ++ ++static struct proj_test_param g_proj_test_param; ++ ++static void etmem_pro_add_name(void) ++{ ++ const char *project_name_long = "project name cannot longer than 32 ppmpppppppppppppppppppppppppppppppppppppppppppppp"; ++ GKeyFile *config = NULL; ++ struct proj_test_param param; ++ ++ init_proj_param(¶m); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_PRO_EXISTED); ++ destroy_proj_config(config); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.proj_name = ""; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.proj_name = project_name_long; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.proj_name = DEFAULT_PROJ; ++} ++ ++static void etmem_pro_add_interval(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.interval = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.interval = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "1199"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "1200"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "1201"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.interval = "abc"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_loop(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.loop = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.loop = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "119"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "120"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "121"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.loop = "abc"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_sleep(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.sleep = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sleep = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "1199"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "1200"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "1201"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sleep = "wrong sleep type"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_lack_loop(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.loop = NULL; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++void test_etmem_prj_add_error(void) ++{ ++ etmem_pro_add_name(); ++ etmem_pro_add_interval(); ++ etmem_pro_add_loop(); ++ etmem_pro_add_sleep(); ++ etmem_pro_lack_loop(); ++} ++ ++void test_etmem_prj_del_error(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.proj_name = ""; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.proj_name = "noexist"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_PRO_NOEXIST); ++ destroy_proj_config(config); ++} ++ ++static void add_project_once(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_PRO_NOEXIST); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_SUCCESS); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ CU_ASSERT_EQUAL(etmemd_project_show("noexist", 0), OPT_PRO_NOEXIST); ++} ++ ++static int add_project_multiple(int proj_add_num) ++{ ++ char project_name_str[PROJECT_NAME_MAX_LEN] = {0}; ++ unsigned int project_num; ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ } ++ ++ CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_show("project_add_del_test_num5", 0), OPT_SUCCESS); ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ } ++ ++ return 0; ++} ++ ++void test_etmem_project_add_ok(void) ++{ ++ add_project_once(); ++ CU_ASSERT_EQUAL(add_project_multiple(PROJECT_ADD_TEST_MAX_NUM), 0); ++} ++ ++void test_etmem_mig_start_error(void) ++{ ++ struct proj_test_param param; ++ ++ init_proj_param(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start(NULL), OPT_INVAL); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(""), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_start("etmem"), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_start("me^$%*mig"), OPT_PRO_NOEXIST); ++ ++ param.proj_name = "add_for_migrate_test"; ++ do_add_proj_test(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_test"), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_test"), OPT_PRO_STARTED); ++ ++ etmemd_stop_all_projects(); ++} ++ ++void test_etmem_mig_stop_error(void) ++{ ++ struct proj_test_param param; ++ ++ init_proj_param(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(NULL), OPT_INVAL); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(""), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("ETMEM"), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("ET^$%*MEM"), OPT_PRO_NOEXIST); ++ ++ param.proj_name = "add_for_migrate_stop_test"; ++ do_add_proj_test(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_stop_test"), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("add_for_migrate_stop_test"), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("add_for_migrate_stop_test"), OPT_PRO_STOPPED); ++ ++ etmemd_stop_all_projects(); ++} ++ ++static int start_project_multiple(int proj_add_num) ++{ ++ char project_name_str[PROJECT_NAME_MAX_LEN] = {0}; ++ unsigned int project_num; ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(project_name_str), OPT_SUCCESS); ++ } ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(project_name_str), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ } ++ ++ return 0; ++} ++ ++void test_etmem_mig_start_ok(void) ++{ ++ CU_ASSERT_EQUAL(start_project_multiple(1), 0); ++ CU_ASSERT_EQUAL(start_project_multiple(PROJECT_ADD_TEST_MAX_NUM), 0); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_project_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_etmem_prj_add_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_prj_del_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_project_add_ok) == NULL || ++ CU_ADD_TEST(suite, test_etmem_mig_start_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_mig_stop_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_mig_start_ok) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_project.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: 0 or 1\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +-- +1.8.3.1 + diff --git a/0057-add-test-for-export-scan.patch b/0057-add-test-for-export-scan.patch new file mode 100644 index 0000000000000000000000000000000000000000..9aa46b1b7ee3c70943e96f07476a145e4acf10ce --- /dev/null +++ b/0057-add-test-for-export-scan.patch @@ -0,0 +1,439 @@ +From 50fb3c7251e423268164627db86c1c312c707e63 Mon Sep 17 00:00:00 2001 +From: Kemeng Shi +Date: Tue, 30 Nov 2021 11:11:01 +0800 +Subject: [PATCH 06/33] add test for export scan + +Signed-off-by: Kemeng Shi +--- + etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt | 28 ++ + .../etmem_scan_ops_llt_test/etmem_scan_ops_llt.c | 383 +++++++++++++++++++++ + 2 files changed, 411 insertions(+) + create mode 100644 etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c + +diff --git a/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..c6ff96c +--- /dev/null ++++ b/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,28 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: shikemeng ++# * Create: 2021-11-30 ++# * Description: CMakefileList for etmem_scan_ops_llt_test ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_scan_ops_llt) ++ ++add_executable(etmem_scan_ops_llt ++ etmem_scan_ops_llt.c ++ ) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt libboundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c b/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c +new file mode 100644 +index 0000000..1856072 +--- /dev/null ++++ b/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c +@@ -0,0 +1,383 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: shikemeng ++ * Create: 2021-11-30 ++ * Description: test for export scan ++ ******************************************************************************/ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_scan.h" ++#include "etmemd_project.h" ++#include "etmemd_engine.h" ++ ++static struct task_pid *alloc_tkpid(unsigned int pid, struct task *tk) ++{ ++ struct task_pid *tpid = NULL; ++ ++ tpid = (struct task_pid *)calloc(1, sizeof(struct task_pid)); ++ CU_ASSERT_PTR_NOT_NULL(tpid); ++ tpid->pid = pid; ++ tpid->tk = tk; ++ ++ return tpid; ++} ++ ++ ++static struct task *alloc_tk(int loop, int sleep) ++{ ++ struct task *tk = NULL; ++ struct project *proj = NULL; ++ struct engine *eng = NULL; ++ ++ proj = (struct project *)calloc(1, sizeof(struct project)); ++ CU_ASSERT_PTR_NOT_NULL(proj); ++ ++ proj->loop = loop; ++ proj->sleep = sleep; ++ ++ tk = (struct task *)calloc(1, sizeof(struct task)); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ eng = calloc(1, sizeof(struct engine)); ++ eng->name = "cslide"; ++ ++ eng->proj = proj; ++ tk->eng = eng; ++ ++ return tk; ++} ++ ++void check_vmas(struct vmas *vmas) ++{ ++ CU_ASSERT_NOT_EQUAL(vmas->vma_cnt, 0); ++ ++ int i; ++ struct vma *curr_vma = NULL; ++ ++ curr_vma = vmas->vma_list; ++ for (i = 0; i < vmas->vma_cnt; i++) { ++ CU_ASSERT_PTR_NOT_NULL(curr_vma); ++ curr_vma = curr_vma->next; ++ } ++} ++ ++static void test_get_vmas_invalid(void) ++{ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ // non-exist pid ++ vmas = etmemd_get_vmas("0", vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ // pid is NULL ++ vmas = etmemd_get_vmas(NULL, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ // pid contains invalid characters ++ vmas = etmemd_get_vmas("1-", vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ // vmflags contains space ++ vmflags_array[0] = "r "; ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ // vmflags length is not 2 ++ vmflags_array[0] = "r"; ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ // vmflags is NULL ++ vmflags_array[0] = NULL; ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ // test free NULL ++ vmas = NULL; ++ etmemd_free_vmas(vmas); ++ ++ etmemd_scan_exit(); ++} ++ ++ ++static void test_get_vmas_valid(void) ++{ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ struct vma *curr_vma = NULL; ++ int i; ++ ++ // get vmas without init ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ ++ etmemd_free_vmas(vmas); ++ ++ // get vmas with init ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ ++ etmemd_free_vmas(vmas); ++ ++ vmas = get_vmas("1"); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ CU_ASSERT_NOT_EQUAL(vmas->vma_cnt, 0); ++ ++ curr_vma = vmas->vma_list; ++ for (i = 0; i < vmas->vma_cnt; i++) { ++ CU_ASSERT_PTR_NOT_NULL(curr_vma); ++ curr_vma = curr_vma->next; ++ } ++ ++ free_vmas(vmas); ++ etmemd_scan_exit(); ++} ++ ++static void test_get_vmas(void) ++{ ++ test_get_vmas_invalid(); ++ test_get_vmas_valid(); ++} ++ ++static void test_get_page_refs_invalid(void) ++{ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ struct page_refs *page_refs = NULL; ++ int flags = SCAN_AS_HUGE | SCAN_IGN_HOST; ++ ++ // free null pointer ++ etmemd_free_page_refs(page_refs); ++ ++ // vmas is NULL ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), -1); ++ ++ // vmas address range invalid ++ vmas = (struct vmas *)calloc(1, sizeof(struct vmas)); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ vmas->vma_cnt = 1; ++ ++ struct vma *vma = (struct vma *)calloc(1, sizeof(struct vma)); ++ CU_ASSERT_PTR_NOT_NULL(vma); ++ vma->start = 0x0ff; ++ vma->end = 0x000; ++ vma->next = NULL; ++ vmas->vma_list = vma; ++ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), -1); ++ etmemd_free_vmas(vmas); ++ ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ ++ // pid not exist ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, "0", &page_refs, flags), -1); ++ CU_ASSERT_PTR_NULL(page_refs); ++ ++ // pid is NULL ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, NULL, &page_refs, flags), -1); ++ CU_ASSERT_PTR_NULL(page_refs); ++ ++ // pid contains invalid chars ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, "--", &page_refs, flags), -1); ++ CU_ASSERT_PTR_NULL(page_refs); ++ ++ etmemd_free_page_refs(page_refs); ++ etmemd_free_vmas(vmas); ++ etmemd_scan_exit(); ++} ++ ++static void test_get_page_refs_valid() ++{ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ struct page_refs *page_refs = NULL; ++ int flags = SCAN_AS_HUGE | SCAN_IGN_HOST; ++ ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), 0); ++ CU_ASSERT_PTR_NOT_NULL(page_refs); ++ ++ unsigned long use_rss; ++ ++ CU_ASSERT_EQUAL(get_page_refs(vmas, pid, &page_refs, &use_rss, 0), 0); ++ CU_ASSERT_PTR_NOT_NULL(page_refs); ++ CU_ASSERT_NOT_EQUAL(use_rss, 0); ++ ++ etmemd_free_page_refs(page_refs); ++ etmemd_free_vmas(vmas); ++ etmemd_scan_exit(); ++} ++ ++static void test_get_page_refs(void) ++{ ++ test_get_page_refs_invalid(); ++ test_get_page_refs_valid(); ++} ++ ++static void test_scan_error(void) ++{ ++ unsigned int pid_error = 1111111111; ++ int loop = 1; ++ int sleep = 1; ++ struct task_pid *tpid = NULL; ++ struct task *tk = NULL; ++ ++ tk = alloc_tk(loop, sleep); ++ tpid = alloc_tkpid(pid_error, tk); ++ ++ CU_ASSERT_PTR_NULL(etmemd_do_scan(tpid, NULL)); ++ CU_ASSERT_PTR_NULL(etmemd_do_scan(tpid, tk)); ++ ++ free(tk); ++ free(tpid); ++} ++ ++static void test_etmem_scan_ok(void) ++{ ++ unsigned int pid_ok = 1; ++ int loop = 1; ++ int sleep = 1; ++ struct page_refs *page_refs = NULL; ++ struct task_pid *tpid = NULL; ++ struct task *tk = NULL; ++ ++ tk = alloc_tk(loop, sleep); ++ tpid = alloc_tkpid(pid_ok, tk); ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ page_refs = etmemd_do_scan(tpid, tk); ++ CU_ASSERT_PTR_NOT_NULL(page_refs); ++ free(tk); ++ free(tpid); ++ clean_page_refs_unexpected(&page_refs); ++ CU_ASSERT_PTR_NULL(page_refs); ++ etmemd_scan_exit(); ++} ++ ++static void test_add_pg_to_mem_grade() ++{ ++ const char *pid = "1"; ++ struct vmas *vma = NULL; ++ struct page_refs *page_refs = NULL; ++ struct page_refs *list = NULL; ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ vma = get_vmas(pid); ++ CU_ASSERT_EQUAL(get_page_refs(vma, pid, &page_refs, NULL, 0), 0); ++ page_refs = add_page_refs_into_memory_grade(page_refs, &list); ++ CU_ASSERT_PTR_NOT_NULL(page_refs); ++ CU_ASSERT_PTR_NOT_NULL(list); ++ ++ free(list); ++ etmemd_free_page_refs(page_refs); ++ free_vmas(vma); ++ etmemd_scan_exit(); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_scan_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_get_vmas) == NULL || ++ CU_ADD_TEST(suite, test_get_page_refs) == NULL || ++ CU_ADD_TEST(suite, test_scan_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_scan_ok) == NULL || ++ CU_ADD_TEST(suite, test_add_pg_to_mem_grade) == NULL) { ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_scan.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: 0 or 1\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +-- +1.8.3.1 + diff --git a/0058-add-code-of-testcase-for-etmem-common-function.patch b/0058-add-code-of-testcase-for-etmem-common-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..583df69201e5277271b82d36db1767e47adf00ca --- /dev/null +++ b/0058-add-code-of-testcase-for-etmem-common-function.patch @@ -0,0 +1,1436 @@ +From f4b6e6e9e15d7bfb3e82d7b5a59157adf49fc426 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Wed, 8 Dec 2021 16:11:36 +0800 +Subject: [PATCH 07/33] add code of testcase for etmem common function + +--- + .../test/etmem_common_func_llt_test/CMakeLists.txt | 27 ++ + .../etmem_common_func_llt.c | 315 ++++++++++++++ + .../test_systemd_service.sh | 35 ++ + .../test/etmem_project_ops_llt_test/CMakeLists.txt | 28 ++ + .../etmem_project_ops_llt.c | 468 +++++++++++++++++++++ + etmem/test/project/CMakeLists.txt | 28 -- + etmem/test/project/etmem_project_ops_llt.c | 468 --------------------- + 7 files changed, 873 insertions(+), 496 deletions(-) + create mode 100644 etmem/test/etmem_common_func_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c + create mode 100755 etmem/test/etmem_common_func_llt_test/test_systemd_service.sh + create mode 100644 etmem/test/etmem_project_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c + delete mode 100644 etmem/test/project/CMakeLists.txt + delete mode 100644 etmem/test/project/etmem_project_ops_llt.c + +diff --git a/etmem/test/etmem_common_func_llt_test/CMakeLists.txt b/etmem/test/etmem_common_func_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..be3b365 +--- /dev/null ++++ b/etmem/test/etmem_common_func_llt_test/CMakeLists.txt +@@ -0,0 +1,27 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-07 ++# * Description: CMakefileList for etmem_common_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_common_func_llt) ++ ++add_executable(${EXE} ++etmem_common_func_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c b/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c +new file mode 100644 +index 0000000..2bb5b11 +--- /dev/null ++++ b/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c +@@ -0,0 +1,315 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-12-07 ++ * Description: This is a source file of the unit test for common function in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_common.h" ++#include "etmemd_engine.h" ++#include "etmemd_rpc.h" ++ ++static void clean_flags(bool *ishelp) ++{ ++ *ishelp = false; ++ optarg = NULL; ++ optind = 0; ++} ++ ++static void test_parse_cmdline_error(void) ++{ ++ bool is_help = false; ++ char *cmd[] = {"./etmemd"}; ++ char *cmd_error_para[] = {"./etmemd", "-d"}; ++ char *cmd_error_help[] = {"./etmemd", "help"}; ++ char *cmd_err_help[] = {"./etmemd", "---help"}; ++ char *cmd_error_log[] = {"./etmemd", "-l"}; ++ char *cmd_lack_sock[] = {"./etmemd", "-l", "0"}; ++ char *cmd_sock_lack_para[] = {"./etmemd", "-l", "0", "-s"}; ++ char *cmd_sock_err[] = {"./etmemd", "-l", "0", "1", "-s"}; ++ char *cmd_mul_log[] = {"./etmemd", "-l", "0", "-l", "0"}; ++ char *cmd_mul_sock[] = {"./etmemd", "-s", "sock0", "-s", "sock1"}; ++ char *cmd_para_too_long[] = {"./etmemd", "-l", "0", "-l", "0", "-s", "sock"}; ++ char *cmd_para_redundant[] = {"./etmemd", "-l", "0", "-h", "-s", "sock"}; ++ char *cmd_lack_s[] = {"./etmemd", "-l", "0", "-h"}; ++ char *cmd_unwanted_para[] = {"./etmemd", "-l", "0", "-d", "file"}; ++ ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(0, NULL, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd) / sizeof(cmd[0]), cmd, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_error_para) / sizeof(cmd_error_para[0]), cmd_error_para, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_error_help) / sizeof(cmd_error_help[0]), cmd_error_help, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_err_help) / sizeof(cmd_err_help[0]), cmd_err_help, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_error_log) / sizeof(cmd_error_log[0]), cmd_error_log, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_lack_sock) / sizeof(cmd_lack_sock[0]), cmd_lack_sock, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_sock_lack_para) / sizeof(cmd_sock_lack_para[0]), cmd_sock_lack_para, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_sock_err) / sizeof(cmd_sock_err[0]), cmd_sock_err, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_mul_log) / sizeof(cmd_mul_log[0]), cmd_mul_log, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_mul_sock) / sizeof(cmd_mul_sock[0]), cmd_mul_sock, &is_help), -1); ++ etmemd_sock_name_free(); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_para_too_long) / sizeof(cmd_para_too_long[0]), cmd_para_too_long, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_para_redundant) / sizeof(cmd_para_redundant[0]), cmd_para_redundant, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_lack_s) / sizeof(cmd_lack_s[0]), cmd_lack_s, &is_help), -1); ++ clean_flags(&is_help); ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_unwanted_para) / sizeof(cmd_unwanted_para[0]), cmd_unwanted_para, &is_help), -1); ++ clean_flags(&is_help); ++} ++ ++static void test_parse_cmdline_ok(void) ++{ ++ bool is_help = false; ++ char *cmd[] = {"./etmemd", "-h"}; ++ char *cmd_h[] = {"./etmemd", "-help"}; ++ char *cmd_help[] = {"./etmemd", "--help"}; ++ char *cmd_ok[] = {"./etmemd", "-l", "0", "-s", "cmd_ok"}; ++ char *cmd_only_sock[] = {"./etmemd", "-s", "cmd_only_sock"}; ++ ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd) / sizeof(cmd[0]), cmd, &is_help), 0); ++ etmemd_sock_name_free(); ++ clean_flags(&is_help); ++ ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_ok) / sizeof(cmd_ok[0]), cmd_ok, &is_help), 0); ++ clean_flags(&is_help); ++ ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_h) / sizeof(cmd_h[0]), cmd_h, &is_help), 0); ++ clean_flags(&is_help); ++ ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_help) / sizeof(cmd_help[0]), cmd_help, &is_help), 0); ++ clean_flags(&is_help); ++ ++ CU_ASSERT_EQUAL(etmemd_parse_cmdline(sizeof(cmd_only_sock) / sizeof(cmd_only_sock[0]), cmd_only_sock, &is_help), 0); ++ etmemd_sock_name_free(); ++ clean_flags(&is_help); ++} ++ ++static void test_get_int_value_error(void) ++{ ++ int value; ++ ++ CU_ASSERT_EQUAL(get_int_value("a1", &value), -1); ++ CU_ASSERT_EQUAL(get_int_value("-2147483649", &value), -1); ++ CU_ASSERT_EQUAL(get_int_value("2147483648", &value), -1); ++} ++ ++static void test_get_int_value_ok(void) ++{ ++ int value; ++ ++ CU_ASSERT_EQUAL(get_int_value("-2147483648", &value), 0); ++ CU_ASSERT_EQUAL(value, INT_MIN); ++ CU_ASSERT_EQUAL(get_int_value("-2147483647", &value), 0); ++ CU_ASSERT_EQUAL(value, INT_MIN + 1); ++ CU_ASSERT_EQUAL(get_int_value("0", &value), 0); ++ CU_ASSERT_EQUAL(value, 0); ++ CU_ASSERT_EQUAL(get_int_value("2147483646", &value), 0); ++ CU_ASSERT_EQUAL(value, INT_MAX - 1); ++ CU_ASSERT_EQUAL(get_int_value("2147483647", &value), 0); ++ CU_ASSERT_EQUAL(value, INT_MAX); ++} ++ ++static void test_get_uint_value_error(void) ++{ ++ unsigned int value; ++ ++ CU_ASSERT_EQUAL(get_unsigned_int_value("a1", &value), -1); ++ CU_ASSERT_EQUAL(get_unsigned_int_value("-1", &value), -1); ++ CU_ASSERT_EQUAL(get_unsigned_int_value("4294967296", &value), -1); ++} ++ ++static void test_get_uint_value_ok(void) ++{ ++ unsigned int value; ++ ++ CU_ASSERT_EQUAL(get_unsigned_int_value("0", &value), 0); ++ CU_ASSERT_EQUAL(value, 0); ++ CU_ASSERT_EQUAL(get_unsigned_int_value("1", &value), 0); ++ CU_ASSERT_EQUAL(value, 1); ++ CU_ASSERT_EQUAL(get_unsigned_int_value("4294967294", &value), 0); ++ CU_ASSERT_EQUAL(value, UINT_MAX - 1); ++ CU_ASSERT_EQUAL(get_unsigned_int_value("4294967295", &value), 0); ++ CU_ASSERT_EQUAL(value, UINT_MAX); ++} ++ ++static void test_get_proc_file_error(void) ++{ ++ CU_ASSERT_PTR_NULL(etmemd_get_proc_file("0", "/maps", 0, "r")); ++ CU_ASSERT_PTR_NULL(etmemd_get_proc_file("1", "maps", 0, "r")); ++ CU_ASSERT_PTR_NULL(etmemd_get_proc_file("1", "/map", 0, "r")); ++} ++ ++static void test_get_proc_file_ok(void) ++{ ++ FILE *fp = NULL; ++ ++ fp = etmemd_get_proc_file("1", "/maps", 0, "r"); ++ ++ CU_ASSERT_EQUAL(fclose(fp), 0); ++} ++ ++static void test_get_key_value_error(void) ++{ ++ char key[KEY_VALUE_MAX_LEN] = {}; ++ char value[KEY_VALUE_MAX_LEN] = {}; ++ ++ CU_ASSERT_EQUAL(get_keyword_and_value("", key, value), -1); ++ CU_ASSERT_EQUAL(get_keyword_and_value("abcd", key, value), -1); ++ CU_ASSERT_EQUAL(get_keyword_and_value(":1", key, value), -1); ++ CU_ASSERT_EQUAL(get_keyword_and_value("a:", key, value), -1); ++ CU_ASSERT_EQUAL(get_keyword_and_value("#a:1", key, value), -1); ++ CU_ASSERT_EQUAL(get_keyword_and_value("a.b:1", key, value), -1); ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop:2*4", key, value), -1); ++} ++ ++static void test_get_key_value_ok(void) ++{ ++ char key[KEY_VALUE_MAX_LEN] = {}; ++ char value[KEY_VALUE_MAX_LEN] = {}; ++ ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop:30", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "loop"); ++ CU_ASSERT_STRING_EQUAL(value, "30"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop 30", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "loop"); ++ CU_ASSERT_STRING_EQUAL(value, "30"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop\t30", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "loop"); ++ CU_ASSERT_STRING_EQUAL(value, "30"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop :30", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "loop"); ++ CU_ASSERT_STRING_EQUAL(value, "30"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop\t:30", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "loop"); ++ CU_ASSERT_STRING_EQUAL(value, "30"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("loop\t 30", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "loop"); ++ CU_ASSERT_STRING_EQUAL(value, "30"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("a_b:1", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "a_b"); ++ CU_ASSERT_STRING_EQUAL(value, "1"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("%P:1", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "%P"); ++ CU_ASSERT_STRING_EQUAL(value, "1"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("%P:0.2", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "%P"); ++ CU_ASSERT_STRING_EQUAL(value, "0.2"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("%P:20%", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "%P"); ++ CU_ASSERT_STRING_EQUAL(value, "20%"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("output:/var/run", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "output"); ++ CU_ASSERT_STRING_EQUAL(value, "/var/run"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("engine:dynamic_fb", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "engine"); ++ CU_ASSERT_STRING_EQUAL(value, "dynamic_fb"); ++ CU_ASSERT_EQUAL(get_keyword_and_value("name:qemu-kvm", key, value), 0); ++ CU_ASSERT_STRING_EQUAL(key, "name"); ++ CU_ASSERT_STRING_EQUAL(value, "qemu-kvm"); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++void test_etmem_systemd_service_0001(void) ++{ ++ CU_ASSERT_EQUAL(system("../etmem_common_func_llt_test/test_systemd_service.sh"), 0); ++} ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_common_func", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_get_int_value_error) == NULL || ++ CU_ADD_TEST(suite, test_get_int_value_ok) == NULL || ++ CU_ADD_TEST(suite, test_get_uint_value_error) == NULL || ++ CU_ADD_TEST(suite, test_get_uint_value_ok) == NULL || ++ CU_ADD_TEST(suite, test_get_key_value_error) == NULL || ++ CU_ADD_TEST(suite, test_get_key_value_ok) == NULL || ++ CU_ADD_TEST(suite, test_parse_cmdline_error) == NULL || ++ CU_ADD_TEST(suite, test_parse_cmdline_ok) == NULL || ++ CU_ADD_TEST(suite, test_get_proc_file_error) == NULL || ++ CU_ADD_TEST(suite, test_get_proc_file_ok) == NULL || ++ CU_ADD_TEST(suite, test_etmem_systemd_service_0001) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_common.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: 0 or 1\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_common_func_llt_test/test_systemd_service.sh b/etmem/test/etmem_common_func_llt_test/test_systemd_service.sh +new file mode 100755 +index 0000000..852ad8c +--- /dev/null ++++ b/etmem/test/etmem_common_func_llt_test/test_systemd_service.sh +@@ -0,0 +1,35 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-07 ++# * Description: This is a shell script of the unit test for etmem commont functions ++# ******************************************************************************/ ++ ++test_start_as_service() ++{ ++ ./bin/etmemd -l 0 -s dt_socket -m & ++ etmemd_pid=$! ++ echo "etmemd_pid ${etmemd_pid}" ++ sleep 1 ++ ./bin/etmem obj add -f ../conf/conf_slide/config_file -s dt_socket ++ if [ "$?" != "0" ];then ++ echo "add config fail to etmemd service unexpected" ++ exit 1 ++ fi ++ ps -aux |grep -v grep |grep "etmemd -l 0 -s dt_socket -m" ++ if [ "$?" != "0" ];then ++ echo "etmemd service exit unexpected after add config" ++ exit 1 ++ fi ++ killall etmemd ++} ++ ++test_start_as_service +diff --git a/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..70cd530 +--- /dev/null ++++ b/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,28 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-11-29 ++# * Description: CMakefileList for etmem_project_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(../common) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_project_ops_llt) ++ ++add_executable(${EXE} ++etmem_project_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so ${BUILD_DIR}/lib/libtest.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c b/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c +new file mode 100644 +index 0000000..edd2330 +--- /dev/null ++++ b/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c +@@ -0,0 +1,468 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-11-29 ++ * Description: This is a source file of the unit test for project-related commands in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "etmemd_project.h" ++#include "etmemd_file.h" ++#include "etmemd_common.h" ++#include "securec.h" ++ ++#include "test_common.h" ++ ++#include ++#include ++#include ++ ++#define PROJECT_ADD_TEST_MAX_NUM 50 ++ ++static struct proj_test_param g_proj_test_param; ++ ++static void etmem_pro_add_name(void) ++{ ++ const char *project_name_long = "project name cannot longer than 32 ppmpppppppppppppppppppppppppppppppppppppppppppppp"; ++ GKeyFile *config = NULL; ++ struct proj_test_param param; ++ ++ init_proj_param(¶m); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_PRO_EXISTED); ++ destroy_proj_config(config); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.proj_name = ""; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.proj_name = project_name_long; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.proj_name = DEFAULT_PROJ; ++} ++ ++static void etmem_pro_add_interval(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.interval = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.interval = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "1199"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "1200"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.interval = "1201"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.interval = "abc"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_loop(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.loop = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.loop = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "119"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "120"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.loop = "121"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.loop = "abc"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_sleep(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.sleep = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sleep = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "1199"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "1200"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sleep = "1201"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sleep = "wrong sleep type"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_lack_loop(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.loop = NULL; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++void test_etmem_prj_add_error(void) ++{ ++ etmem_pro_add_name(); ++ etmem_pro_add_interval(); ++ etmem_pro_add_loop(); ++ etmem_pro_add_sleep(); ++ etmem_pro_lack_loop(); ++} ++ ++void test_etmem_prj_del_error(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.proj_name = ""; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.proj_name = "noexist"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_PRO_NOEXIST); ++ destroy_proj_config(config); ++} ++ ++static void add_project_once(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_PRO_NOEXIST); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_SUCCESS); ++ ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ CU_ASSERT_EQUAL(etmemd_project_show("noexist", 0), OPT_PRO_NOEXIST); ++} ++ ++static int add_project_multiple(int proj_add_num) ++{ ++ char project_name_str[PROJECT_NAME_MAX_LEN] = {0}; ++ unsigned int project_num; ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ } ++ ++ CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_show("project_add_del_test_num5", 0), OPT_SUCCESS); ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ } ++ ++ return 0; ++} ++ ++void test_etmem_project_add_ok(void) ++{ ++ add_project_once(); ++ CU_ASSERT_EQUAL(add_project_multiple(PROJECT_ADD_TEST_MAX_NUM), 0); ++} ++ ++void test_etmem_mig_start_error(void) ++{ ++ struct proj_test_param param; ++ ++ init_proj_param(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start(NULL), OPT_INVAL); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(""), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_start("etmem"), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_start("me^$%*mig"), OPT_PRO_NOEXIST); ++ ++ param.proj_name = "add_for_migrate_test"; ++ do_add_proj_test(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_test"), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_test"), OPT_PRO_STARTED); ++ ++ etmemd_stop_all_projects(); ++} ++ ++void test_etmem_mig_stop_error(void) ++{ ++ struct proj_test_param param; ++ ++ init_proj_param(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(NULL), OPT_INVAL); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(""), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("ETMEM"), OPT_PRO_NOEXIST); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("ET^$%*MEM"), OPT_PRO_NOEXIST); ++ ++ param.proj_name = "add_for_migrate_stop_test"; ++ do_add_proj_test(¶m); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_stop_test"), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("add_for_migrate_stop_test"), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop("add_for_migrate_stop_test"), OPT_PRO_STOPPED); ++ ++ etmemd_stop_all_projects(); ++} ++ ++static int start_project_multiple(int proj_add_num) ++{ ++ char project_name_str[PROJECT_NAME_MAX_LEN] = {0}; ++ unsigned int project_num; ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(project_name_str), OPT_SUCCESS); ++ } ++ ++ for (project_num = 0; project_num < proj_add_num; project_num++) { ++ if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", ++ project_num) <= 0) { ++ printf("get project_name wrong.\n"); ++ return -1; ++ } ++ param.proj_name = project_name_str; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(project_name_str), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ } ++ ++ return 0; ++} ++ ++void test_etmem_mig_start_ok(void) ++{ ++ CU_ASSERT_EQUAL(start_project_multiple(1), 0); ++ CU_ASSERT_EQUAL(start_project_multiple(PROJECT_ADD_TEST_MAX_NUM), 0); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_project_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_etmem_prj_add_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_prj_del_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_project_add_ok) == NULL || ++ CU_ADD_TEST(suite, test_etmem_mig_start_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_mig_stop_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_mig_start_ok) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_project.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: 0 or 1\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/project/CMakeLists.txt b/etmem/test/project/CMakeLists.txt +deleted file mode 100644 +index 70cd530..0000000 +--- a/etmem/test/project/CMakeLists.txt ++++ /dev/null +@@ -1,28 +0,0 @@ +-# /****************************************************************************** +-# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. +-# * etmem is licensed under the Mulan PSL v2. +-# * You can use this software according to the terms and conditions of the Mulan PSL v2. +-# * You may obtain a copy of Mulan PSL v2 at: +-# * http://license.coscl.org.cn/MulanPSL2 +-# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +-# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +-# * PURPOSE. +-# * See the Mulan PSL v2 for more details. +-# * Author: liubo +-# * Create: 2021-11-29 +-# * Description: CMakefileList for etmem_project_ops_llt to compile +-# ******************************************************************************/ +- +-project(etmem) +- +-INCLUDE_DIRECTORIES(../../inc/etmem_inc) +-INCLUDE_DIRECTORIES(../../inc/etmemd_inc) +-INCLUDE_DIRECTORIES(../common) +-INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) +- +-SET(EXE etmem_project_ops_llt) +- +-add_executable(${EXE} +-etmem_project_ops_llt.c) +- +-target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so ${BUILD_DIR}/lib/libtest.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/project/etmem_project_ops_llt.c b/etmem/test/project/etmem_project_ops_llt.c +deleted file mode 100644 +index edd2330..0000000 +--- a/etmem/test/project/etmem_project_ops_llt.c ++++ /dev/null +@@ -1,468 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. +- * etmem is licensed under the Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +- * PURPOSE. +- * See the Mulan PSL v2 for more details. +- * Author: liubo +- * Create: 2021-11-29 +- * Description: This is a source file of the unit test for project-related commands in etmem. +- ******************************************************************************/ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "etmemd_project.h" +-#include "etmemd_file.h" +-#include "etmemd_common.h" +-#include "securec.h" +- +-#include "test_common.h" +- +-#include +-#include +-#include +- +-#define PROJECT_ADD_TEST_MAX_NUM 50 +- +-static struct proj_test_param g_proj_test_param; +- +-static void etmem_pro_add_name(void) +-{ +- const char *project_name_long = "project name cannot longer than 32 ppmpppppppppppppppppppppppppppppppppppppppppppppp"; +- GKeyFile *config = NULL; +- struct proj_test_param param; +- +- init_proj_param(¶m); +- +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_PRO_EXISTED); +- destroy_proj_config(config); +- +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.proj_name = ""; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.proj_name = project_name_long; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.proj_name = DEFAULT_PROJ; +-} +- +-static void etmem_pro_add_interval(void) +-{ +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- param.interval = "0"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.interval = "1"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.interval = "2"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.interval = "1199"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.interval = "1200"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.interval = "1201"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.interval = "abc"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +-} +- +-static void etmem_pro_add_loop(void) +-{ +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- param.loop = "0"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.loop = "1"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.loop = "2"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.loop = "119"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.loop = "120"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.loop = "121"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.loop = "abc"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +-} +- +-static void etmem_pro_add_sleep(void) +-{ +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- param.sleep = "0"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.sleep = "1"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.sleep = "2"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.sleep = "1199"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.sleep = "1200"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.sleep = "1201"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +- +- param.sleep = "wrong sleep type"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +-} +- +-static void etmem_pro_lack_loop(void) +-{ +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- param.loop = NULL; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); +- destroy_proj_config(config); +-} +- +-void test_etmem_prj_add_error(void) +-{ +- etmem_pro_add_name(); +- etmem_pro_add_interval(); +- etmem_pro_add_loop(); +- etmem_pro_add_sleep(); +- etmem_pro_lack_loop(); +-} +- +-void test_etmem_prj_del_error(void) +-{ +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- param.proj_name = ""; +- config = construct_proj_config(¶m); +- CU_ASSERT_NOT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- param.proj_name = "noexist"; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_PRO_NOEXIST); +- destroy_proj_config(config); +-} +- +-static void add_project_once(void) +-{ +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_PRO_NOEXIST); +- +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_SUCCESS); +- +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- +- CU_ASSERT_EQUAL(etmemd_project_show("noexist", 0), OPT_PRO_NOEXIST); +-} +- +-static int add_project_multiple(int proj_add_num) +-{ +- char project_name_str[PROJECT_NAME_MAX_LEN] = {0}; +- unsigned int project_num; +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- for (project_num = 0; project_num < proj_add_num; project_num++) { +- if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", +- project_num) <= 0) { +- printf("get project_name wrong.\n"); +- return -1; +- } +- param.proj_name = project_name_str; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- destroy_proj_config(config); +- } +- +- CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_show("project_add_del_test_num5", 0), OPT_SUCCESS); +- +- for (project_num = 0; project_num < proj_add_num; project_num++) { +- if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", +- project_num) <= 0) { +- printf("get project_name wrong.\n"); +- return -1; +- } +- param.proj_name = project_name_str; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- } +- +- return 0; +-} +- +-void test_etmem_project_add_ok(void) +-{ +- add_project_once(); +- CU_ASSERT_EQUAL(add_project_multiple(PROJECT_ADD_TEST_MAX_NUM), 0); +-} +- +-void test_etmem_mig_start_error(void) +-{ +- struct proj_test_param param; +- +- init_proj_param(¶m); +- +- CU_ASSERT_EQUAL(etmemd_migrate_start(NULL), OPT_INVAL); +- CU_ASSERT_EQUAL(etmemd_migrate_start(""), OPT_PRO_NOEXIST); +- CU_ASSERT_EQUAL(etmemd_migrate_start("etmem"), OPT_PRO_NOEXIST); +- CU_ASSERT_EQUAL(etmemd_migrate_start("me^$%*mig"), OPT_PRO_NOEXIST); +- +- param.proj_name = "add_for_migrate_test"; +- do_add_proj_test(¶m); +- +- CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_test"), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_test"), OPT_PRO_STARTED); +- +- etmemd_stop_all_projects(); +-} +- +-void test_etmem_mig_stop_error(void) +-{ +- struct proj_test_param param; +- +- init_proj_param(¶m); +- +- CU_ASSERT_EQUAL(etmemd_migrate_stop(NULL), OPT_INVAL); +- CU_ASSERT_EQUAL(etmemd_migrate_stop(""), OPT_PRO_NOEXIST); +- CU_ASSERT_EQUAL(etmemd_migrate_stop("ETMEM"), OPT_PRO_NOEXIST); +- CU_ASSERT_EQUAL(etmemd_migrate_stop("ET^$%*MEM"), OPT_PRO_NOEXIST); +- +- param.proj_name = "add_for_migrate_stop_test"; +- do_add_proj_test(¶m); +- +- CU_ASSERT_EQUAL(etmemd_migrate_start("add_for_migrate_stop_test"), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_migrate_stop("add_for_migrate_stop_test"), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_migrate_stop("add_for_migrate_stop_test"), OPT_PRO_STOPPED); +- +- etmemd_stop_all_projects(); +-} +- +-static int start_project_multiple(int proj_add_num) +-{ +- char project_name_str[PROJECT_NAME_MAX_LEN] = {0}; +- unsigned int project_num; +- struct proj_test_param param; +- GKeyFile *config = NULL; +- +- init_proj_param(¶m); +- +- for (project_num = 0; project_num < proj_add_num; project_num++) { +- if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", +- project_num) <= 0) { +- printf("get project_name wrong.\n"); +- return -1; +- } +- param.proj_name = project_name_str; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); +- destroy_proj_config(config); +- CU_ASSERT_EQUAL(etmemd_migrate_start(project_name_str), OPT_SUCCESS); +- } +- +- for (project_num = 0; project_num < proj_add_num; project_num++) { +- if (snprintf_s(project_name_str, PROJECT_NAME_MAX_LEN, PROJECT_NAME_MAX_LEN - 1, "project_add_del_test_num%d", +- project_num) <= 0) { +- printf("get project_name wrong.\n"); +- return -1; +- } +- param.proj_name = project_name_str; +- config = construct_proj_config(¶m); +- CU_ASSERT_EQUAL(etmemd_migrate_stop(project_name_str), OPT_SUCCESS); +- CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); +- destroy_proj_config(config); +- } +- +- return 0; +-} +- +-void test_etmem_mig_start_ok(void) +-{ +- CU_ASSERT_EQUAL(start_project_multiple(1), 0); +- CU_ASSERT_EQUAL(start_project_multiple(PROJECT_ADD_TEST_MAX_NUM), 0); +-} +- +-typedef enum { +- CUNIT_SCREEN = 0, +- CUNIT_XMLFILE, +- CUNIT_CONSOLE +-} cu_run_mode; +- +-int main(int argc, const char **argv) +-{ +- CU_pSuite suite; +- CU_pTest pTest; +- unsigned int num_failures; +- cu_run_mode cunit_mode = CUNIT_SCREEN; +- int error_num; +- +- if (argc > 1) { +- cunit_mode = atoi(argv[1]); +- } +- +- if (CU_initialize_registry() != CUE_SUCCESS) { +- return -CU_get_error(); +- } +- +- suite = CU_add_suite("etmem_project_ops", NULL, NULL); +- if (suite == NULL) { +- goto ERROR; +- } +- +- if (CU_ADD_TEST(suite, test_etmem_prj_add_error) == NULL || +- CU_ADD_TEST(suite, test_etmem_prj_del_error) == NULL || +- CU_ADD_TEST(suite, test_etmem_project_add_ok) == NULL || +- CU_ADD_TEST(suite, test_etmem_mig_start_error) == NULL || +- CU_ADD_TEST(suite, test_etmem_mig_stop_error) == NULL || +- CU_ADD_TEST(suite, test_etmem_mig_start_ok) == NULL) { +- printf("CU_ADD_TEST fail. \n"); +- goto ERROR; +- } +- +- switch (cunit_mode) { +- case CUNIT_SCREEN: +- CU_basic_set_mode(CU_BRM_VERBOSE); +- CU_basic_run_tests(); +- break; +- case CUNIT_XMLFILE: +- CU_set_output_filename("etmemd_project.c"); +- CU_automated_run_tests(); +- break; +- case CUNIT_CONSOLE: +- CU_console_run_tests(); +- break; +- default: +- printf("not support cunit mode, only support: 0 or 1\n"); +- goto ERROR; +- } +- +- num_failures = CU_get_number_of_failures(); +- CU_cleanup_registry(); +- return num_failures; +- +-ERROR: +- error_num = CU_get_error(); +- CU_cleanup_registry(); +- return -error_num; +-} +-- +1.8.3.1 + diff --git a/0059-add-code-of-testcase-for-etmem-log-ops.patch b/0059-add-code-of-testcase-for-etmem-log-ops.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ec73423e59cb986ed4da0ca4f9652281f665ebb --- /dev/null +++ b/0059-add-code-of-testcase-for-etmem-log-ops.patch @@ -0,0 +1,253 @@ +From 531e313796c9bddc1571f78e858c5bc431b65068 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Tue, 14 Dec 2021 11:09:51 +0800 +Subject: [PATCH 08/33] add code of testcase for etmem log ops + +--- + .../test/etmem_common_func_llt_test/CMakeLists.txt | 3 +- + .../etmem_common_func_llt.c | 3 +- + etmem/test/etmem_log_ops_llt_test/CMakeLists.txt | 26 +++++ + .../etmem_log_ops_llt_test/etmem_log_ops_llt.c | 112 +++++++++++++++++++++ + .../test/etmem_project_ops_llt_test/CMakeLists.txt | 3 +- + .../etmem_project_ops_llt.c | 3 +- + etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt | 4 +- + .../etmem_scan_ops_llt_test/etmem_scan_ops_llt.c | 3 +- + 8 files changed, 147 insertions(+), 10 deletions(-) + create mode 100644 etmem/test/etmem_log_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_log_ops_llt_test/etmem_log_ops_llt.c + +diff --git a/etmem/test/etmem_common_func_llt_test/CMakeLists.txt b/etmem/test/etmem_common_func_llt_test/CMakeLists.txt +index be3b365..205d460 100644 +--- a/etmem/test/etmem_common_func_llt_test/CMakeLists.txt ++++ b/etmem/test/etmem_common_func_llt_test/CMakeLists.txt +@@ -21,7 +21,6 @@ INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) + + SET(EXE etmem_common_func_llt) + +-add_executable(${EXE} +-etmem_common_func_llt.c) ++add_executable(${EXE} etmem_common_func_llt.c) + + target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c b/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c +index 2bb5b11..f195d4d 100644 +--- a/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c ++++ b/etmem/test/etmem_common_func_llt_test/etmem_common_func_llt.c +@@ -300,7 +300,8 @@ int main(int argc, const char **argv) + CU_console_run_tests(); + break; + default: +- printf("not support cunit mode, only support: 0 or 1\n"); ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); + goto ERROR; + } + +diff --git a/etmem/test/etmem_log_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_log_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..322fe0f +--- /dev/null ++++ b/etmem/test/etmem_log_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,26 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-10 ++# * Description: CMakefileList for etmem_log_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_log_ops_llt) ++ ++add_executable(${EXE} etmem_log_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_log_ops_llt_test/etmem_log_ops_llt.c b/etmem/test/etmem_log_ops_llt_test/etmem_log_ops_llt.c +new file mode 100644 +index 0000000..e9a7402 +--- /dev/null ++++ b/etmem/test/etmem_log_ops_llt_test/etmem_log_ops_llt.c +@@ -0,0 +1,112 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-12-10 ++ * Description: This is a source file of the unit test for log functions in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include "etmemd_log.h" ++ ++#include ++#include ++#include ++ ++#define ETMEMD_LOG_WRONG (-1) ++ ++static void test_basic_log_level(void) ++{ ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_WRONG), -1); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_DEBUG), 0); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_INFO), 0); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_WARN), 0); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_ERR), 0); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_INVAL), -1); ++} ++ ++static void test_etmem_log_print(void) ++{ ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_DEBUG), 0); ++ etmemd_log(ETMEMD_LOG_DEBUG, "test_etmem_log_debug_level\n"); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_INFO), 0); ++ etmemd_log(ETMEMD_LOG_INFO, "test_etmem_log_info_level\n"); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_WARN), 0); ++ etmemd_log(ETMEMD_LOG_WARN, "test_etmem_log_warn_level\n"); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_ERR), 0); ++ etmemd_log(ETMEMD_LOG_ERR, "test_etmem_log_error_level\n"); ++ CU_ASSERT_EQUAL(etmemd_init_log_level(ETMEMD_LOG_INVAL), -1); ++ etmemd_log(ETMEMD_LOG_INVAL, "test_etmem_log_interval_level\n"); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_log_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_basic_log_level) == NULL || ++ CU_ADD_TEST(suite, test_etmem_log_print) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_log.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt +index 70cd530..ff3f310 100644 +--- a/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt ++++ b/etmem/test/etmem_project_ops_llt_test/CMakeLists.txt +@@ -22,7 +22,6 @@ INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) + + SET(EXE etmem_project_ops_llt) + +-add_executable(${EXE} +-etmem_project_ops_llt.c) ++add_executable(${EXE} etmem_project_ops_llt.c) + + target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so ${BUILD_DIR}/lib/libtest.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c b/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c +index edd2330..a01e8e8 100644 +--- a/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c ++++ b/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c +@@ -453,7 +453,8 @@ int main(int argc, const char **argv) + CU_console_run_tests(); + break; + default: +- printf("not support cunit mode, only support: 0 or 1\n"); ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); + goto ERROR; + } + +diff --git a/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt +index c6ff96c..b5378b8 100644 +--- a/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt ++++ b/etmem/test/etmem_scan_ops_llt_test/CMakeLists.txt +@@ -21,8 +21,6 @@ INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) + + SET(EXE etmem_scan_ops_llt) + +-add_executable(etmem_scan_ops_llt +- etmem_scan_ops_llt.c +- ) ++add_executable(${EXE} etmem_scan_ops_llt.c) + + target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt libboundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c b/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c +index 1856072..0cd2ecc 100644 +--- a/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c ++++ b/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c +@@ -368,7 +368,8 @@ int main(int argc, const char **argv) + CU_console_run_tests(); + break; + default: +- printf("not support cunit mode, only support: 0 or 1\n"); ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); + goto ERROR; + } + +-- +1.8.3.1 + diff --git a/0060-add-make-install-support-to-CMakeList.patch b/0060-add-make-install-support-to-CMakeList.patch new file mode 100644 index 0000000000000000000000000000000000000000..220a0107cc30ba30fca4ce2cfa42c2c70516d062 --- /dev/null +++ b/0060-add-make-install-support-to-CMakeList.patch @@ -0,0 +1,29 @@ +From 31731fdc3fbd8afd8daeba2138344568cbd6a238 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Tue, 21 Dec 2021 21:16:52 +0800 +Subject: [PATCH 10/33] add make install support to CMakeList + +--- + etmem/CMakeLists.txt | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/etmem/CMakeLists.txt b/etmem/CMakeLists.txt +index b5eb83e..9fba791 100644 +--- a/etmem/CMakeLists.txt ++++ b/etmem/CMakeLists.txt +@@ -123,3 +123,12 @@ if( ${ARCHITECTURE} STREQUAL "aarch64" ) + else() + target_compile_options(etmemd_scan PRIVATE -march=core-avx-i -m64) + endif() ++ ++install(TARGETS etmem etmemd ++ PERMISSIONS OWNER_READ OWNER_EXECUTE ++ RUNTIME DESTINATION /usr/bin) ++ ++install(DIRECTORY ${PROJECT_SOURCE_DIR}/conf/ ++ DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE ++ FILE_PERMISSIONS OWNER_READ OWNER_WRITE ++ DESTINATION /etc/etmem) +-- +1.8.3.1 + diff --git a/0061-add-region-scan.patch b/0061-add-region-scan.patch new file mode 100644 index 0000000000000000000000000000000000000000..a2626f5c1aa35e1f1fc73422858fa3635e923837 --- /dev/null +++ b/0061-add-region-scan.patch @@ -0,0 +1,1315 @@ +From caeab903170cd7745b9c8ab3c5ebbc4fd9d8b30d Mon Sep 17 00:00:00 2001 +From: geruijun +Date: Thu, 28 Oct 2021 15:45:40 +0800 +Subject: [PATCH 11/33] add region scan + +Signed-off-by: geruijun +--- + etmem/CMakeLists.txt | 3 +- + etmem/conf/cslide_conf.yaml | 1 + + etmem/conf/damon_conf.yaml | 26 ++ + etmem/conf/slide_conf.yaml | 1 + + etmem/conf/thirdparty_conf.yaml | 1 + + etmem/inc/etmemd_inc/etmemd_damon.h | 25 ++ + etmem/inc/etmemd_inc/etmemd_engine.h | 1 + + etmem/inc/etmemd_inc/etmemd_file.h | 10 + + etmem/inc/etmemd_inc/etmemd_project_exp.h | 24 +- + etmem/src/etmem_src/etmem_obj.c | 2 +- + etmem/src/etmemd_src/etmemd_common.c | 5 +- + etmem/src/etmemd_src/etmemd_cslide.c | 9 +- + etmem/src/etmemd_src/etmemd_damon.c | 573 +++++++++++++++++++++++++++++ + etmem/src/etmemd_src/etmemd_engine.c | 2 + + etmem/src/etmemd_src/etmemd_file.c | 2 +- + etmem/src/etmemd_src/etmemd_pool_adapter.c | 4 +- + etmem/src/etmemd_src/etmemd_project.c | 207 ++++++++++- + etmem/src/etmemd_src/etmemd_scan.c | 11 +- + etmem/src/etmemd_src/etmemd_slide.c | 6 +- + 19 files changed, 879 insertions(+), 34 deletions(-) + create mode 100644 etmem/conf/damon_conf.yaml + create mode 100644 etmem/inc/etmemd_inc/etmemd_damon.h + create mode 100644 etmem/src/etmemd_src/etmemd_damon.c + +diff --git a/etmem/CMakeLists.txt b/etmem/CMakeLists.txt +index b5eb83e..e067fe5 100644 +--- a/etmem/CMakeLists.txt ++++ b/etmem/CMakeLists.txt +@@ -40,7 +40,8 @@ set(ETMEMD_SRC + ${ETMEMD_SRC_DIR}/etmemd_threadpool.c + ${ETMEMD_SRC_DIR}/etmemd_threadtimer.c + ${ETMEMD_SRC_DIR}/etmemd_pool_adapter.c +- ${ETMEMD_SRC_DIR}/etmemd_migrate.c) ++ ${ETMEMD_SRC_DIR}/etmemd_migrate.c ++ ${ETMEMD_SRC_DIR}/etmemd_damon.c) + + set(ETMEM_SRC + ${ETMEM_SRC_DIR}/etmem.c +diff --git a/etmem/conf/cslide_conf.yaml b/etmem/conf/cslide_conf.yaml +index 6b6ecc3..6455065 100644 +--- a/etmem/conf/cslide_conf.yaml ++++ b/etmem/conf/cslide_conf.yaml +@@ -1,5 +1,6 @@ + [project] + name=test ++scan_type=page + loop=1 + interval=1 + sleep=1 +diff --git a/etmem/conf/damon_conf.yaml b/etmem/conf/damon_conf.yaml +new file mode 100644 +index 0000000..1a53a46 +--- /dev/null ++++ b/etmem/conf/damon_conf.yaml +@@ -0,0 +1,26 @@ ++[project] ++name=test ++scan_type=region ++sample_interval=5000 ++aggr_interval=100000 ++update_interval=1000000 ++min_nr_regions=10 ++max_nr_regions=1000 ++ ++[engine] ++name=damon ++project=test ++min_size=0 ++max_size=4294967295 ++min_acc=0 ++max_acc=2 ++min_age=0 ++max_age=4294967295 ++action=pageout ++ ++[task] ++project=test ++engine=damon ++name=background_damon ++type=name ++value=mysqld +diff --git a/etmem/conf/slide_conf.yaml b/etmem/conf/slide_conf.yaml +index b99ab50..75f0220 100644 +--- a/etmem/conf/slide_conf.yaml ++++ b/etmem/conf/slide_conf.yaml +@@ -1,5 +1,6 @@ + [project] + name=test ++scan_type=page + loop=1 + interval=1 + sleep=1 +diff --git a/etmem/conf/thirdparty_conf.yaml b/etmem/conf/thirdparty_conf.yaml +index 1e1e9ac..c488ed2 100644 +--- a/etmem/conf/thirdparty_conf.yaml ++++ b/etmem/conf/thirdparty_conf.yaml +@@ -1,5 +1,6 @@ + [project] + name=test ++scan_type=page + loop=1 + interval=1 + sleep=1 +diff --git a/etmem/inc/etmemd_inc/etmemd_damon.h b/etmem/inc/etmemd_inc/etmemd_damon.h +new file mode 100644 +index 0000000..cc9c36f +--- /dev/null ++++ b/etmem/inc/etmemd_inc/etmemd_damon.h +@@ -0,0 +1,25 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: geruijun ++ * Create: 2021-10-28 ++ * Description: This is a header file of damon engine. ++ ******************************************************************************/ ++ ++#ifndef ETMEMD_DAMON_H ++#define ETMEMD_DAMON_H ++ ++#include "etmemd_project.h" ++ ++int etmemd_start_damon(struct project *proj); ++int etmemd_stop_damon(void); ++int fill_engine_type_damon(struct engine *eng, GKeyFile *config); ++ ++#endif +diff --git a/etmem/inc/etmemd_inc/etmemd_engine.h b/etmem/inc/etmemd_inc/etmemd_engine.h +index 9a50e10..7750c8b 100644 +--- a/etmem/inc/etmemd_inc/etmemd_engine.h ++++ b/etmem/inc/etmemd_inc/etmemd_engine.h +@@ -25,6 +25,7 @@ enum eng_type { + SLIDE_ENGINE = 0, + CSLIDE_ENGINE, + MEMDCD_ENGINE, ++ DAMON_ENGINE, + DYNAMIC_FB_ENGINE, + HISTORICAL_FB_ENGINE, + THIRDPARTY_ENGINE, +diff --git a/etmem/inc/etmemd_inc/etmemd_file.h b/etmem/inc/etmemd_inc/etmemd_file.h +index 34ccaf9..de2d4ad 100644 +--- a/etmem/inc/etmemd_inc/etmemd_file.h ++++ b/etmem/inc/etmemd_inc/etmemd_file.h +@@ -44,4 +44,14 @@ static inline int parse_to_int(void *val) + return (int)(long long)val; + } + ++static inline unsigned int parse_to_uint(void *val) ++{ ++ return (unsigned int)(long long)val; ++} ++ ++static inline unsigned long parse_to_ulong(void *val) ++{ ++ return (unsigned long)(long long)val; ++} ++ + #endif +diff --git a/etmem/inc/etmemd_inc/etmemd_project_exp.h b/etmem/inc/etmemd_inc/etmemd_project_exp.h +index bcd5108..8740f7e 100644 +--- a/etmem/inc/etmemd_inc/etmemd_project_exp.h ++++ b/etmem/inc/etmemd_inc/etmemd_project_exp.h +@@ -19,15 +19,35 @@ + #include + #include + +-struct project { +- char *name; ++enum scan_type { ++ PAGE_SCAN = 0, ++ REGION_SCAN, ++}; ++ ++struct page_scan { + int interval; + int loop; + int sleep; ++}; ++ ++struct region_scan { ++ unsigned long sample_interval; ++ unsigned long aggr_interval; ++ unsigned long update_interval; ++ unsigned long min_nr_regions; ++ unsigned long max_nr_regions; ++}; ++ ++struct project { ++ char *name; ++ enum scan_type type; ++ void *scan_param; + bool start; + struct engine *engs; + + SLIST_ENTRY(project) entry; + }; + ++int scan_fill_by_conf(GKeyFile *config, struct project *proj); ++ + #endif +diff --git a/etmem/src/etmem_src/etmem_obj.c b/etmem/src/etmem_src/etmem_obj.c +index a5517ea..1a05a47 100644 +--- a/etmem/src/etmem_src/etmem_obj.c ++++ b/etmem/src/etmem_src/etmem_obj.c +@@ -57,7 +57,7 @@ static int obj_parse_cmd(struct etmem_conf *conf, struct mem_proj *proj) + } + } + +- printf("obj cmd %s is not supportted.\n", cmd); ++ printf("obj cmd %s is not supported.\n", cmd); + return -1; + } + +diff --git a/etmem/src/etmemd_src/etmemd_common.c b/etmem/src/etmemd_src/etmemd_common.c +index 4595499..ebf6232 100644 +--- a/etmem/src/etmemd_src/etmemd_common.c ++++ b/etmem/src/etmemd_src/etmemd_common.c +@@ -198,16 +198,19 @@ int get_unsigned_int_value(const char *val, unsigned int *value) + int get_unsigned_long_value(const char *val, unsigned long *value) + { + char *pos = NULL; ++ unsigned long value_tmp; + + errno = 0; +- *value = strtoul(val, &pos, DECIMAL_RADIX); ++ value_tmp = strtoul(val, &pos, DECIMAL_RADIX); + if (check_str_format(pos[0])) { + etmemd_log(ETMEMD_LOG_ERR, "invalid value, must be type of unsigned long.\n"); + return -1; + } + ++ *value = value_tmp; + return 0; + } ++ + void etmemd_safe_free(void **ptr) + { + if (ptr == NULL || *ptr == NULL) { +diff --git a/etmem/src/etmemd_src/etmemd_cslide.c b/etmem/src/etmemd_src/etmemd_cslide.c +index ad3eff8..b3d1637 100644 +--- a/etmem/src/etmemd_src/etmemd_cslide.c ++++ b/etmem/src/etmemd_src/etmemd_cslide.c +@@ -1818,7 +1818,7 @@ static int cslide_engine_do_cmd(struct engine *eng, struct task *tk, char *cmd, + + item = find_cmd_item(g_task_cmd_items, ARRAY_SIZE(g_task_cmd_items), cmd); + if (item == NULL) { +- etmemd_log(ETMEMD_LOG_ERR, "cslide cmd %s is not supportted\n", cmd); ++ etmemd_log(ETMEMD_LOG_ERR, "cslide cmd %s is not supported\n", cmd); + return -1; + } + if (tk == NULL) { +@@ -2060,6 +2060,7 @@ static struct config_item cslide_eng_config_items[] = { + static int cslide_fill_eng(GKeyFile *config, struct engine *eng) + { + struct cslide_eng_params *params = calloc(1, sizeof(struct cslide_eng_params)); ++ struct page_scan *page_scan = (struct page_scan *)eng->proj->scan_param; + + if (params == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "alloc cslide engine params fail\n"); +@@ -2071,9 +2072,9 @@ static int cslide_fill_eng(GKeyFile *config, struct engine *eng) + goto free_eng_params; + } + +- params->loop = eng->proj->loop; +- params->interval = eng->proj->interval; +- params->sleep = eng->proj->sleep; ++ params->loop = page_scan->loop; ++ params->interval = page_scan->interval; ++ params->sleep = page_scan->sleep; + if (parse_file_config(config, ENG_GROUP, cslide_eng_config_items, + ARRAY_SIZE(cslide_eng_config_items), (void *)params) != 0) { + etmemd_log(ETMEMD_LOG_ERR, "cslide fill engine params fail\n"); +diff --git a/etmem/src/etmemd_src/etmemd_damon.c b/etmem/src/etmemd_src/etmemd_damon.c +new file mode 100644 +index 0000000..aa6d1b3 +--- /dev/null ++++ b/etmem/src/etmemd_src/etmemd_damon.c +@@ -0,0 +1,573 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: geruijun ++ * Create: 2021-10-28 ++ * Description: Add etmemd damon engine. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++ ++#include "securec.h" ++#include "etmemd_log.h" ++#include "etmemd_common.h" ++#include "etmemd_file.h" ++#include "etmemd_engine.h" ++#include "etmemd_task.h" ++#include "etmemd_task_exp.h" ++#include "etmemd_scan.h" ++#include "etmemd_damon.h" ++ ++#define KERNEL_DAMON_PATH "/sys/kernel/debug/damon/" ++#define DAMON_PARAM_TARGET_IDS "target_ids" ++#define DAMON_PARAM_ATTRS "attrs" ++#define DAMON_PARAM_SCHEMES "schemes" ++#define DAMON_PARAM_MONITOR_ON "monitor_on" ++ ++#define ON_LEN 2 ++#define OFF_LEN 3 ++#define INT_MAX_LEN 10 ++#define NUM_OF_ATTRS 5 ++#define NUM_OF_SCHEMES 7 ++ ++enum damos_action { ++ DAMOS_WILLNEED, ++ DAMOS_COLD, ++ DAMOS_PAGEOUT, ++ DAMOS_HUGEPAGE, ++ DAMOS_NOHUGEPAGE, ++ DAMOS_STAT, ++}; ++ ++struct action_item { ++ char *action_str; ++ enum damos_action action_type; ++}; ++ ++struct damon_eng_params { ++ unsigned long min_sz_region; ++ unsigned long max_sz_region; ++ unsigned int min_nr_accesses; ++ unsigned int max_nr_accesses; ++ unsigned int min_age_region; ++ unsigned int max_age_region; ++ enum damos_action action; ++}; ++ ++static bool check_damon_exist(void) ++{ ++ if (access(KERNEL_DAMON_PATH, F_OK) != 0) { ++ return false; ++ } ++ return true; ++} ++ ++static FILE *get_damon_file(const char *file) ++{ ++ char *file_name = NULL; ++ size_t file_str_size; ++ FILE *fp = NULL; ++ ++ file_str_size = strlen(KERNEL_DAMON_PATH) + strlen(file) + 1; ++ file_name = (char *)calloc(file_str_size, sizeof(char)); ++ if (file_name == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc for damon file %s fail\n", file); ++ return NULL; ++ } ++ ++ if (snprintf_s(file_name, file_str_size, file_str_size - 1, "%s%s", ++ KERNEL_DAMON_PATH, file) == -1) { ++ etmemd_log(ETMEMD_LOG_ERR, "snprintf for damon file %s fail\n", file); ++ goto out; ++ } ++ ++ fp = fopen(file_name, "r+"); ++ if (fp == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "open file %s fail\n", file_name); ++ } ++ ++out: ++ free(file_name); ++ return fp; ++} ++ ++static bool is_engs_valid(struct project *proj) ++{ ++ struct engine *eng = proj->engs; ++ ++ while (eng != NULL) { ++ if (strcmp(eng->name, "damon") != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "engine type %s not supported, only support damon engine in region scan\n", ++ eng->name); ++ return false; ++ } ++ eng = eng->next; ++ } ++ ++ return true; ++} ++ ++static int get_damon_pids_val_and_num(struct task *tk, int *nr_tasks) ++{ ++ while (tk != NULL) { ++ if (etmemd_get_task_pids(tk, false) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "damon fail to get task pids\n"); ++ *nr_tasks = 0; ++ return -1; ++ } ++ (*nr_tasks)++; ++ tk = tk->next; ++ } ++ ++ return 0; ++} ++ ++static char *get_damon_pids_str(struct task *tk, const int nr_tasks) ++{ ++ char *pids = NULL; ++ size_t pids_size; ++ char tmp_pid[PID_STR_MAX_LEN + 2] = {0}; // plus 2 for space and '\0' follow pid ++ ++ pids_size = (PID_STR_MAX_LEN + 1) * nr_tasks + 1; ++ pids = (char *)calloc(pids_size, sizeof(char)); ++ if (pids == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc for pids in damon fail\n"); ++ return NULL; ++ } ++ ++ while (tk != NULL) { ++ if (snprintf_s(tmp_pid, PID_STR_MAX_LEN + 2, PID_STR_MAX_LEN + 1, ++ "%u ", tk->pids->pid) == -1) { ++ etmemd_log(ETMEMD_LOG_WARN, "snprintf pid %u in damon fail\n", tk->pids->pid); ++ tk = tk->next; ++ continue; ++ } ++ ++ if (strcat_s(pids, pids_size, tmp_pid) != EOK) { ++ etmemd_log(ETMEMD_LOG_WARN, "strcat pid %s fail\n", tmp_pid); ++ } ++ tk = tk->next; ++ } ++ ++ return pids; ++} ++ ++static int set_damon_target_ids(struct project *proj) ++{ ++ FILE *fp = NULL; ++ int nr_tasks = 0; ++ struct task *tk = proj->engs->tasks; ++ char *pids_str = NULL; ++ size_t pids_len; ++ int ret = -1; ++ ++ if (!is_engs_valid(proj)) { ++ goto out; ++ } ++ ++ fp = get_damon_file(DAMON_PARAM_TARGET_IDS); ++ if (fp == NULL) { ++ goto out; ++ } ++ ++ if (get_damon_pids_val_and_num(tk, &nr_tasks) != 0) { ++ goto out_close; ++ } ++ ++ pids_str = get_damon_pids_str(tk, nr_tasks); ++ if (pids_str == NULL) { ++ goto out_close; ++ } ++ ++ pids_len = strlen(pids_str); ++ if (pids_len == 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get all task pids fail in damon\n"); ++ goto out_free; ++ } ++ ++ if (fwrite(pids_str, sizeof(char), pids_len + 1, fp) != pids_len + 1) { ++ etmemd_log(ETMEMD_LOG_ERR, "write pids to damon fail\n"); ++ goto out_free; ++ } ++ ret = 0; ++ ++out_free: ++ free(pids_str); ++out_close: ++ fclose(fp); ++out: ++ return ret; ++} ++ ++static char *get_damon_attrs_str(struct project *proj) ++{ ++ char *attrs = NULL; ++ size_t attrs_size; ++ struct region_scan *reg_scan = (struct region_scan *)proj->scan_param; ++ ++ attrs_size = (INT_MAX_LEN + 1) * NUM_OF_ATTRS; ++ attrs = (char *)calloc(attrs_size, sizeof(char)); ++ if (attrs == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc for attrs in damon fail\n"); ++ return NULL; ++ } ++ ++ if (snprintf_s(attrs, attrs_size, attrs_size - 1, "%lu %lu %lu %lu %lu", ++ reg_scan->sample_interval, reg_scan->aggr_interval, ++ reg_scan->update_interval, reg_scan->min_nr_regions, ++ reg_scan->max_nr_regions) == -1) { ++ etmemd_log(ETMEMD_LOG_ERR, "snprintf for attrs fail\n"); ++ free(attrs); ++ return NULL; ++ } ++ ++ return attrs; ++} ++ ++static int set_damon_attrs(struct project *proj) ++{ ++ FILE *fp = NULL; ++ char *attrs_str = NULL; ++ size_t attrs_len; ++ int ret = -1; ++ ++ fp = get_damon_file(DAMON_PARAM_ATTRS); ++ if (fp == NULL) { ++ goto out; ++ } ++ ++ attrs_str = get_damon_attrs_str(proj); ++ if (attrs_str == NULL) { ++ goto out_close; ++ } ++ ++ attrs_len = strlen(attrs_str); ++ if (fwrite(attrs_str, sizeof(char), attrs_len + 1, fp) != attrs_len + 1) { ++ etmemd_log(ETMEMD_LOG_ERR, "write attrs to damon fail\n"); ++ goto out_free; ++ } ++ ret = 0; ++ ++out_free: ++ free(attrs_str); ++out_close: ++ fclose(fp); ++out: ++ return ret; ++} ++ ++static char *get_damon_schemes_str(struct project *proj) ++{ ++ char *schemes = NULL; ++ size_t schemes_size; ++ struct damon_eng_params *params = (struct damon_eng_params *)proj->engs->params; ++ ++ schemes_size = (INT_MAX_LEN + 1) * NUM_OF_SCHEMES; ++ schemes = (char *)calloc(schemes_size, sizeof(char)); ++ if (schemes == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc for schemes in damon fail\n"); ++ return NULL; ++ } ++ ++ if (snprintf_s(schemes, schemes_size, schemes_size - 1, "%lu %lu %u %u %u %u %d", ++ params->min_sz_region, params->max_sz_region, ++ params->min_nr_accesses, params->max_nr_accesses, ++ params->min_age_region, params->max_age_region, ++ params->action) == -1) { ++ etmemd_log(ETMEMD_LOG_ERR, "snprintf for schemes fail\n"); ++ free(schemes); ++ return NULL; ++ } ++ ++ return schemes; ++} ++ ++static int set_damon_schemes(struct project *proj) ++{ ++ FILE *fp = NULL; ++ char *schemes_str = NULL; ++ size_t schemes_len; ++ int ret = -1; ++ ++ fp = get_damon_file(DAMON_PARAM_SCHEMES); ++ if (fp == NULL) { ++ goto out; ++ } ++ ++ schemes_str = get_damon_schemes_str(proj); ++ if (schemes_str == NULL) { ++ goto out_close; ++ } ++ ++ schemes_len = strlen(schemes_str); ++ if (fwrite(schemes_str, sizeof(char), schemes_len + 1, fp) != schemes_len + 1) { ++ etmemd_log(ETMEMD_LOG_ERR, "write schemes to damon fail\n"); ++ goto out_free; ++ } ++ ret = 0; ++ ++out_free: ++ free(schemes_str); ++out_close: ++ fclose(fp); ++out: ++ return ret; ++} ++ ++static char *get_damon_monitor_on_str(bool start) ++{ ++ char *switch_str = NULL; ++ size_t switch_size; ++ ++ switch_size = start ? ON_LEN + 1 : OFF_LEN + 1; ++ switch_str = (char *)calloc(switch_size, sizeof(char)); ++ if (switch_str == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc for switch in damon fail\n"); ++ return NULL; ++ } ++ if (snprintf_s(switch_str, switch_size, switch_size - 1, start ? "on" : "off") == -1) { ++ etmemd_log(ETMEMD_LOG_ERR, "snprintf for switch fail\n"); ++ free(switch_str); ++ return NULL; ++ } ++ ++ return switch_str; ++} ++ ++static int set_damon_monitor_on(bool start) ++{ ++ FILE *fp = NULL; ++ int ret = -1; ++ char *switch_str = NULL; ++ size_t switch_len; ++ ++ fp = get_damon_file(DAMON_PARAM_MONITOR_ON); ++ if (fp == NULL) { ++ goto out; ++ } ++ ++ switch_str = get_damon_monitor_on_str(start); ++ if (switch_str == NULL) { ++ goto out_close; ++ } ++ ++ switch_len = strlen(switch_str); ++ if (fwrite(switch_str, sizeof(char), switch_len + 1, fp) != switch_len + 1) { ++ etmemd_log(ETMEMD_LOG_ERR, "write monitor_on to damon fail\n"); ++ goto out_free; ++ } ++ ret = 0; ++ ++out_free: ++ free(switch_str); ++out_close: ++ fclose(fp); ++out: ++ return ret; ++} ++ ++int etmemd_start_damon(struct project *proj) ++{ ++ bool start = true; ++ ++ if (proj == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "proj should not be NULL\n"); ++ return -1; ++ } ++ ++ if (!check_damon_exist()) { ++ etmemd_log(ETMEMD_LOG_ERR, "kernel damon module not exist\n"); ++ return -1; ++ } ++ ++ if (set_damon_target_ids(proj) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "set damon pids fail\n"); ++ return -1; ++ } ++ ++ if (set_damon_attrs(proj) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "set damon attrs fail\n"); ++ return -1; ++ } ++ ++ if (set_damon_schemes(proj) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "set damon schemes fail\n"); ++ return -1; ++ } ++ ++ if (set_damon_monitor_on(start) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "set damon monitor_on to on fail\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int etmemd_stop_damon(void) ++{ ++ bool start = false; ++ ++ if (!check_damon_exist()) { ++ etmemd_log(ETMEMD_LOG_ERR, "kernel damon module not exist\n"); ++ return -1; ++ } ++ ++ if (set_damon_monitor_on(start) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "set damon monitor_on to off fail\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int fill_min_size(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ unsigned long min_size = parse_to_ulong(val); ++ ++ params->min_sz_region = min_size; ++ return 0; ++} ++ ++static int fill_max_size(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ unsigned long max_size = parse_to_ulong(val); ++ ++ params->max_sz_region = max_size; ++ return 0; ++} ++ ++static int fill_min_acc(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ unsigned int min_acc = parse_to_uint(val); ++ ++ params->min_nr_accesses = min_acc; ++ return 0; ++} ++ ++static int fill_max_acc(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ unsigned int max_acc = parse_to_uint(val); ++ ++ params->max_nr_accesses = max_acc; ++ return 0; ++} ++ ++static int fill_min_age(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ unsigned int min_age = parse_to_uint(val); ++ ++ params->min_age_region = min_age; ++ return 0; ++} ++ ++static int fill_max_age(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ unsigned int max_age = parse_to_uint(val); ++ ++ params->max_age_region = max_age; ++ return 0; ++} ++ ++static struct action_item damon_action_items[] = { ++ {"willneed", DAMOS_WILLNEED}, ++ {"cold", DAMOS_COLD}, ++ {"pageout", DAMOS_PAGEOUT}, ++ {"hugepage", DAMOS_HUGEPAGE}, ++ {"nohugepage", DAMOS_NOHUGEPAGE}, ++ {"stat", DAMOS_STAT}, ++}; ++ ++static int fill_action(void *obj, void *val) ++{ ++ struct damon_eng_params *params = (struct damon_eng_params *)obj; ++ char *action = (char *)val; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(damon_action_items); i++) { ++ if (strcmp(action, damon_action_items[i].action_str) == 0) { ++ params->action = damon_action_items[i].action_type; ++ free(action); ++ return 0; ++ } ++ } ++ ++ free(action); ++ return -1; ++} ++ ++static struct config_item damon_eng_config_items[] = { ++ {"min_size", INT_VAL, fill_min_size, false}, ++ {"max_size", INT_VAL, fill_max_size, false}, ++ {"min_acc", INT_VAL, fill_min_acc, false}, ++ {"max_acc", INT_VAL, fill_max_acc, false}, ++ {"min_age", INT_VAL, fill_min_age, false}, ++ {"max_age", INT_VAL, fill_max_age, false}, ++ {"action", STR_VAL, fill_action, false}, ++}; ++ ++static int damon_fill_eng(GKeyFile *config, struct engine *eng) ++{ ++ struct damon_eng_params *params = calloc(1, sizeof(struct damon_eng_params)); ++ ++ if (params == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "alloc damon engine params fail\n"); ++ return -1; ++ } ++ ++ if (parse_file_config(config, ENG_GROUP, damon_eng_config_items, ++ ARRAY_SIZE(damon_eng_config_items), (void *)params) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "damon fill engine params fail.\n"); ++ free(params); ++ return -1; ++ } ++ ++ eng->params = (void *)params; ++ return 0; ++} ++ ++static void damon_clear_eng(struct engine *eng) ++{ ++ struct damon_eng_params *eng_params = (struct damon_eng_params *)eng->params; ++ ++ if (eng_params == NULL) { ++ return; ++ } ++ ++ free(eng_params); ++ eng->params = NULL; ++} ++ ++struct engine_ops g_damon_eng_ops = { ++ .fill_eng_params = damon_fill_eng, ++ .clear_eng_params = damon_clear_eng, ++ .fill_task_params = NULL, ++ .clear_task_params = NULL, ++ .start_task = NULL, ++ .stop_task = NULL, ++ .alloc_pid_params = NULL, ++ .free_pid_params = NULL, ++ .eng_mgt_func = NULL, ++}; ++ ++int fill_engine_type_damon(struct engine *eng, GKeyFile *config) ++{ ++ eng->ops = &g_damon_eng_ops; ++ eng->engine_type = DAMON_ENGINE; ++ eng->name = "damon"; ++ return 0; ++} +diff --git a/etmem/src/etmemd_src/etmemd_engine.c b/etmem/src/etmemd_src/etmemd_engine.c +index 6a14ecb..de17db7 100644 +--- a/etmem/src/etmemd_src/etmemd_engine.c ++++ b/etmem/src/etmemd_src/etmemd_engine.c +@@ -19,6 +19,7 @@ + #include "etmemd_slide.h" + #include "etmemd_cslide.h" + #include "etmemd_memdcd.h" ++#include "etmemd_damon.h" + #include "etmemd_thirdparty.h" + #include "etmemd_log.h" + #include "etmemd_common.h" +@@ -38,6 +39,7 @@ static struct engine_add_item g_engine_add_items[] = { + {"slide", fill_engine_type_slide}, + {"cslide", fill_engine_type_cslide}, + {"memdcd", fill_engine_type_memdcd}, ++ {"damon", fill_engine_type_damon}, + {"thirdparty", fill_engine_type_thirdparty}, + }; + +diff --git a/etmem/src/etmemd_src/etmemd_file.c b/etmem/src/etmemd_src/etmemd_file.c +index 8b478c6..b7dc27f 100644 +--- a/etmem/src/etmemd_src/etmemd_file.c ++++ b/etmem/src/etmemd_src/etmemd_file.c +@@ -31,7 +31,7 @@ static int parse_item(GKeyFile *config, char *group_name, struct config_item *it + + switch (item->type) { + case INT_VAL: +- val = (void *)(long long)g_key_file_get_integer(config, group_name, item->key, &error); ++ val = (void *)(long long)g_key_file_get_int64(config, group_name, item->key, &error); + break; + case STR_VAL: + val = (void *)g_key_file_get_string(config, group_name, item->key, &error); +diff --git a/etmem/src/etmemd_src/etmemd_pool_adapter.c b/etmem/src/etmemd_src/etmemd_pool_adapter.c +index 8c0068e..dfda3f4 100644 +--- a/etmem/src/etmemd_src/etmemd_pool_adapter.c ++++ b/etmem/src/etmemd_src/etmemd_pool_adapter.c +@@ -18,6 +18,7 @@ + #include + #include "etmemd_pool_adapter.h" + #include "etmemd_engine.h" ++#include "etmemd_scan.h" + + static void push_ctrl_workflow(struct task_pid **tk_pid, void *(*exector)(void *)) + { +@@ -77,6 +78,7 @@ static void *launch_threadtimer_executor(void *arg) + int start_threadpool_work(struct task_executor *executor) + { + struct task *tk = executor->tk; ++ struct page_scan *page_scan = (struct page_scan *)tk->eng->proj->scan_param; + + etmemd_log(ETMEMD_LOG_DEBUG, "start etmem for Task_value %s, project_name %s\n", + tk->value, tk->eng->proj->name); +@@ -89,7 +91,7 @@ int start_threadpool_work(struct task_executor *executor) + return -1; + } + +- tk->timer_inst = thread_timer_create(tk->eng->proj->interval); ++ tk->timer_inst = thread_timer_create(page_scan->interval); + if (tk->timer_inst == NULL) { + threadpool_stop_and_destroy(&tk->threadpool_inst); + etmemd_log(ETMEMD_LOG_ERR, "Timer task creation failed for project <%s> task <%s>.\n", +diff --git a/etmem/src/etmemd_src/etmemd_project.c b/etmem/src/etmemd_src/etmemd_project.c +index f7f1885..fa4293b 100644 +--- a/etmem/src/etmemd_src/etmemd_project.c ++++ b/etmem/src/etmemd_src/etmemd_project.c +@@ -25,6 +25,7 @@ + #include "securec.h" + #include "etmemd_project.h" + #include "etmemd_engine.h" ++#include "etmemd_damon.h" + #include "etmemd_common.h" + #include "etmemd_file.h" + #include "etmemd_log.h" +@@ -34,6 +35,7 @@ + #define MAX_LOOP_VALUE 120 + + #define MAX_OBJ_NAME_LEN 64 ++#define MIN_NR_MIN_VAL 3 + + static SLIST_HEAD(project_list, project) g_projects = SLIST_HEAD_INITIALIZER(g_projects); + +@@ -452,9 +454,9 @@ static int fill_project_name(void *obj, void *val) + return 0; + } + +-static int fill_project_loop(void *obj, void *val) ++static int fill_page_scan_loop(void *obj, void *val) + { +- struct project *proj = (struct project *)obj; ++ struct page_scan *scan = (struct page_scan *)obj; + int loop = parse_to_int(val); + if (loop < 1 || loop > MAX_LOOP_VALUE) { + etmemd_log(ETMEMD_LOG_ERR, "invalid project loop value %d, it must be between 1 and %d.\n", +@@ -462,13 +464,13 @@ static int fill_project_loop(void *obj, void *val) + return -1; + } + +- proj->loop = loop; ++ scan->loop = loop; + return 0; + } + +-static int fill_project_interval(void *obj, void *val) ++static int fill_page_scan_interval(void *obj, void *val) + { +- struct project *proj = (struct project *)obj; ++ struct page_scan *scan = (struct page_scan *)obj; + int interval = parse_to_int(val); + if (interval < 1 || interval > MAX_INTERVAL_VALUE) { + etmemd_log(ETMEMD_LOG_ERR, "invalid project interval value %d, it must be between 1 and %d.\n", +@@ -476,13 +478,13 @@ static int fill_project_interval(void *obj, void *val) + return -1; + } + +- proj->interval = interval; ++ scan->interval = interval; + return 0; + } + +-static int fill_project_sleep(void *obj, void *val) ++static int fill_page_scan_sleep(void *obj, void *val) + { +- struct project *proj = (struct project *)obj; ++ struct page_scan *scan = (struct page_scan *)obj; + int sleep = parse_to_int(val); + if (sleep < 1 || sleep > MAX_SLEEP_VALUE) { + etmemd_log(ETMEMD_LOG_ERR, "invalid project sleep value %d, it must be between 1 and %d.\n", +@@ -490,15 +492,147 @@ static int fill_project_sleep(void *obj, void *val) + return -1; + } + +- proj->sleep = sleep; ++ scan->sleep = sleep; ++ return 0; ++} ++ ++struct config_item g_page_scan_config_items[] = { ++ {"loop", INT_VAL, fill_page_scan_loop, false}, ++ {"interval", INT_VAL, fill_page_scan_interval, false}, ++ {"sleep", INT_VAL, fill_page_scan_sleep, false}, ++}; ++ ++static int fill_region_scan_samp_interval(void *obj, void *val) ++{ ++ struct region_scan *scan = (struct region_scan *)obj; ++ unsigned long samp_intvl = parse_to_ulong(val); ++ ++ scan->sample_interval = samp_intvl; ++ return 0; ++} ++ ++static int fill_region_scan_aggr_interval(void *obj, void *val) ++{ ++ struct region_scan *scan = (struct region_scan *)obj; ++ unsigned long aggr_intvl = parse_to_ulong(val); ++ ++ scan->aggr_interval = aggr_intvl; ++ return 0; ++} ++ ++static int fill_region_scan_updt_interval(void *obj, void *val) ++{ ++ struct region_scan *scan = (struct region_scan *)obj; ++ unsigned long updt_intvl = parse_to_ulong(val); ++ ++ scan->update_interval = updt_intvl; ++ return 0; ++} ++ ++static int fill_region_scan_min_nr(void *obj, void *val) ++{ ++ struct region_scan *scan = (struct region_scan *)obj; ++ unsigned long min_nr = parse_to_ulong(val); ++ ++ if (min_nr < MIN_NR_MIN_VAL) { ++ etmemd_log(ETMEMD_LOG_ERR, "invalid minimum nr value %d, it should not be smaller than %d.\n", ++ min_nr, MIN_NR_MIN_VAL); ++ return -1; ++ } ++ ++ scan->min_nr_regions = min_nr; ++ return 0; ++} ++ ++static int fill_region_scan_max_nr(void *obj, void *val) ++{ ++ struct region_scan *scan = (struct region_scan *)obj; ++ unsigned long max_nr = parse_to_ulong(val); ++ ++ if (max_nr < MIN_NR_MIN_VAL) { ++ etmemd_log(ETMEMD_LOG_ERR, "invalid maximum nr value %d, it should not be smaller than %d.\n", ++ max_nr, MIN_NR_MIN_VAL); ++ return -1; ++ } ++ ++ scan->max_nr_regions = max_nr; ++ return 0; ++} ++ ++struct config_item g_region_scan_config_items[] = { ++ {"sample_interval", INT_VAL, fill_region_scan_samp_interval, false}, ++ {"aggr_interval", INT_VAL, fill_region_scan_aggr_interval, false}, ++ {"update_interval", INT_VAL, fill_region_scan_updt_interval, false}, ++ {"min_nr_regions", INT_VAL, fill_region_scan_min_nr, false}, ++ {"max_nr_regions", INT_VAL, fill_region_scan_max_nr, false}, ++}; ++ ++int scan_fill_by_conf(GKeyFile *config, struct project *proj) ++{ ++ struct region_scan *rg_scan = NULL; ++ ++ if (proj->type == PAGE_SCAN) { ++ if (parse_file_config(config, PROJ_GROUP, g_page_scan_config_items, ++ ARRAY_SIZE(g_page_scan_config_items), proj->scan_param) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "parse page scan config fail.\n"); ++ return -1; ++ } ++ } else if (proj->type == REGION_SCAN) { ++ if (parse_file_config(config, PROJ_GROUP, g_region_scan_config_items, ++ ARRAY_SIZE(g_region_scan_config_items), proj->scan_param) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "parse region scan config fail.\n"); ++ return -1; ++ } ++ rg_scan = (struct region_scan *)proj->scan_param; ++ if (rg_scan->min_nr_regions >= rg_scan->max_nr_regions) { ++ etmemd_log(ETMEMD_LOG_ERR, "min_nr_regions %d should be smaller than max_nr_regions %d.\n", ++ rg_scan->min_nr_regions, rg_scan->max_nr_regions); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int fill_project_scan_type(void *obj, void *val) ++{ ++ struct project *proj = (struct project *)obj; ++ char *scan_type = (char *)val; ++ ++ if (strcmp(scan_type, "page") != 0 && strcmp(scan_type, "region") != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "invalid scan type %s, must be page or region\n", ++ scan_type); ++ return -1; ++ } ++ ++ if (strcmp(scan_type, "page") == 0) { ++ struct page_scan *scan = NULL; ++ ++ scan = (struct page_scan *)calloc(1, sizeof(struct page_scan)); ++ if (scan == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc fail\n"); ++ return -1; ++ } ++ proj->scan_param = (void *)scan; ++ proj->type = PAGE_SCAN; ++ } else { ++ struct region_scan *scan = NULL; ++ ++ scan = (struct region_scan *)calloc(1, sizeof(struct region_scan)); ++ if (scan == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "malloc fail\n"); ++ return -1; ++ } ++ proj->scan_param = (void *)scan; ++ proj->type = REGION_SCAN; ++ } ++ + return 0; + } + + static struct config_item g_project_config_items[] = { + {"name", STR_VAL, fill_project_name, false}, +- {"loop", INT_VAL, fill_project_loop, false}, +- {"interval", INT_VAL, fill_project_interval, false}, +- {"sleep", INT_VAL, fill_project_sleep, false}, ++ {"scan_type", STR_VAL, fill_project_scan_type, false}, + }; + + static void clear_project(struct project *proj) +@@ -507,6 +641,11 @@ static void clear_project(struct project *proj) + free(proj->name); + proj->name = NULL; + } ++ ++ if (proj->scan_param != NULL) { ++ free(proj->scan_param); ++ proj->scan_param = NULL; ++ } + } + + static int project_fill_by_conf(GKeyFile *config, struct project *proj) +@@ -555,6 +694,13 @@ enum opt_result etmemd_project_add(GKeyFile *config) + proj = NULL; + return OPT_INVAL; + } ++ if (scan_fill_by_conf(config, proj) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "fill scan parameter from configuration file fail\n"); ++ clear_project(proj); ++ free(proj); ++ proj = NULL; ++ return OPT_INVAL; ++ } + + SLIST_INSERT_HEAD(&g_projects, proj, entry); + return OPT_SUCCESS; +@@ -665,9 +811,22 @@ enum opt_result etmemd_migrate_start(const char *project_name) + return OPT_PRO_STARTED; + } + +- if (start_tasks(proj) != 0) { +- etmemd_log(ETMEMD_LOG_ERR, "some task of project %s start fail\n", project_name); +- return OPT_INTER_ERR; ++ switch (proj->type) { ++ case PAGE_SCAN: ++ if (start_tasks(proj) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "some task of project %s start fail\n", project_name); ++ return OPT_INTER_ERR; ++ } ++ break; ++ case REGION_SCAN: ++ if (etmemd_start_damon(proj) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "start damon of project %s fail\n", project_name); ++ return OPT_INTER_ERR; ++ } ++ break; ++ default: ++ etmemd_log(ETMEMD_LOG_ERR, "scan type %d not support\n", proj->type); ++ return OPT_INVAL; + } + + proj->start = true; +@@ -694,9 +853,23 @@ enum opt_result etmemd_migrate_stop(const char *project_name) + proj->name); + return OPT_PRO_STOPPED; + } +- stop_tasks(proj); +- proj->start = false; + ++ switch (proj->type) { ++ case PAGE_SCAN: ++ stop_tasks(proj); ++ break; ++ case REGION_SCAN: ++ if (etmemd_stop_damon() != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "stop damon of project %s fail\n", project_name); ++ return OPT_INTER_ERR; ++ } ++ break; ++ default: ++ etmemd_log(ETMEMD_LOG_ERR, "scan type %d not support\n", proj->type); ++ return OPT_INVAL; ++ } ++ ++ proj->start = false; + return OPT_SUCCESS; + } + +diff --git a/etmem/src/etmemd_src/etmemd_scan.c b/etmem/src/etmemd_src/etmemd_scan.c +index fec6373..3ee018e 100644 +--- a/etmem/src/etmemd_src/etmemd_scan.c ++++ b/etmem/src/etmemd_src/etmemd_scan.c +@@ -761,6 +761,8 @@ struct page_refs *etmemd_do_scan(const struct task_pid *tpid, const struct task + return NULL; + } + ++ struct page_scan *page_scan = (struct page_scan *)tk->eng->proj->scan_param; ++ + if (snprintf_s(pid, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%u", tpid->pid) <= 0) { + etmemd_log(ETMEMD_LOG_ERR, "snprintf pid fail %u", tpid->pid); + return NULL; +@@ -774,7 +776,7 @@ struct page_refs *etmemd_do_scan(const struct task_pid *tpid, const struct task + } + + /* loop for scanning idle_pages to get result of memory access. */ +- for (i = 0; i < tk->eng->proj->loop; i++) { ++ for (i = 0; i < page_scan->loop; i++) { + ret = get_page_refs(vmas, pid, &page_refs, NULL, 0); + if (ret != 0) { + etmemd_log(ETMEMD_LOG_ERR, "scan operation failed\n"); +@@ -783,7 +785,7 @@ struct page_refs *etmemd_do_scan(const struct task_pid *tpid, const struct task + page_refs = NULL; + break; + } +- sleep((unsigned)tk->eng->proj->sleep); ++ sleep((unsigned)page_scan->sleep); + } + + free_vmas(vmas); +@@ -841,6 +843,7 @@ void clean_page_sort_unexpected(void *arg) + struct page_sort *alloc_page_sort(const struct task_pid *tpid) + { + struct page_sort *page_sort = NULL; ++ struct page_scan *page_scan = (struct page_scan *)tpid->tk->eng->proj->scan_param; + + page_sort = (struct page_sort *)calloc(1, sizeof(struct page_sort)); + if (page_sort == NULL) { +@@ -848,9 +851,9 @@ struct page_sort *alloc_page_sort(const struct task_pid *tpid) + return NULL; + } + +- page_sort->loop = tpid->tk->eng->proj->loop; ++ page_sort->loop = page_scan->loop; + +- page_sort->page_refs_sort = (struct page_refs **)calloc((tpid->tk->eng->proj->loop + 1), sizeof(struct page_refs *)); ++ page_sort->page_refs_sort = (struct page_refs **)calloc((page_scan->loop + 1), sizeof(struct page_refs *)); + if (page_sort->page_refs_sort == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "calloc page refs sort failed.\n"); + free(page_sort); +diff --git a/etmem/src/etmemd_src/etmemd_slide.c b/etmem/src/etmemd_src/etmemd_slide.c +index 45db00a..8362224 100644 +--- a/etmem/src/etmemd_src/etmemd_slide.c ++++ b/etmem/src/etmemd_src/etmemd_slide.c +@@ -35,6 +35,7 @@ static struct memory_grade *slide_policy_interface(struct page_sort **page_sort, + struct memory_grade *memory_grade = NULL; + unsigned long need_2_swap_num; + volatile uint64_t count = 0; ++ struct page_scan *page_scan = (struct page_scan *)tpid->tk->eng->proj->scan_param; + + if (slide_params == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "cannot get params for slide\n"); +@@ -65,7 +66,7 @@ static struct memory_grade *slide_policy_interface(struct page_sort **page_sort, + if (need_2_swap_num == 0) + goto count_out; + +- for (int i = 0; i < tpid->tk->eng->proj->loop + 1; i++) { ++ for (int i = 0; i < page_scan->loop + 1; i++) { + page_refs = &((*page_sort)->page_refs_sort[i]); + + while (*page_refs != NULL) { +@@ -201,6 +202,7 @@ static struct config_item g_slide_task_config_items[] = { + static int slide_fill_task(GKeyFile *config, struct task *tk) + { + struct slide_params *params = calloc(1, sizeof(struct slide_params)); ++ struct page_scan *page_scan = (struct page_scan *)tk->eng->proj->scan_param; + + if (params == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "alloc slide param fail\n"); +@@ -213,7 +215,7 @@ static int slide_fill_task(GKeyFile *config, struct task *tk) + goto free_params; + } + +- if (params->t > tk->eng->proj->loop * WRITE_TYPE_WEIGHT) { ++ if (params->t > page_scan->loop * WRITE_TYPE_WEIGHT) { + etmemd_log(ETMEMD_LOG_ERR, "engine param T must less than loop.\n"); + goto free_params; + } +-- +1.8.3.1 + diff --git a/0062-fix-etmem-build-problem.patch b/0062-fix-etmem-build-problem.patch new file mode 100644 index 0000000000000000000000000000000000000000..dfdd66912f342c269c670a424ccc7566d78c9cc2 --- /dev/null +++ b/0062-fix-etmem-build-problem.patch @@ -0,0 +1,58 @@ +From 37264d5a2f7fe27092b0f8d2e834a70e3108a68d Mon Sep 17 00:00:00 2001 +From: liubo +Date: Sat, 15 Jan 2022 15:01:47 +0800 +Subject: [PATCH 12/33] fix etmem build problem + +--- + etmem/src/etmemd_src/etmemd_memdcd.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/etmem/src/etmemd_src/etmemd_memdcd.c b/etmem/src/etmemd_src/etmemd_memdcd.c +index 28590e2..7e2f657 100644 +--- a/etmem/src/etmemd_src/etmemd_memdcd.c ++++ b/etmem/src/etmemd_src/etmemd_memdcd.c +@@ -243,6 +243,7 @@ static struct page_refs *memdcd_do_scan(const struct task_pid *tpid, const struc + int ret = 0; + char pid[PID_STR_MAX_LEN] = {0}; + char *us = "us"; ++ struct page_scan *page_scan = NULL; + + if(tpid == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "task pid is null\n"); +@@ -254,6 +255,8 @@ static struct page_refs *memdcd_do_scan(const struct task_pid *tpid, const struc + return NULL; + } + ++ page_scan = (struct page_scan *)tk->eng->proj->scan_param; ++ + if (snprintf_s(pid, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%u", tpid->pid) <= 0) { + etmemd_log(ETMEMD_LOG_ERR, "snprintf pid fail %u", tpid->pid); + return NULL; +@@ -266,7 +269,7 @@ static struct page_refs *memdcd_do_scan(const struct task_pid *tpid, const struc + } + + /* loop for scanning idle_pages to get result of memory access. */ +- for (i = 0; i < tk->eng->proj->loop; i++) { ++ for (i = 0; i < page_scan->loop; i++) { + ret = get_page_refs(vmas, pid, &page_refs, NULL, 0); + if (ret != 0) { + etmemd_log(ETMEMD_LOG_ERR, "scan operation failed\n"); +@@ -275,7 +278,7 @@ static struct page_refs *memdcd_do_scan(const struct task_pid *tpid, const struc + page_refs = NULL; + break; + } +- sleep((unsigned)tk->eng->proj->sleep); ++ sleep((unsigned)page_scan->sleep); + } + + free_vmas(vmas); +@@ -419,4 +422,4 @@ int fill_engine_type_memdcd(struct engine *eng, GKeyFile *config) + eng->engine_type = MEMDCD_ENGINE; + eng->name = "memdcd"; + return 0; +-} +\ No newline at end of file ++} +-- +1.8.3.1 + diff --git a/0063-etmem-add-code-of-testcase.patch b/0063-etmem-add-code-of-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6cda3424232042ec10b2850fc5829a058c0afdf --- /dev/null +++ b/0063-etmem-add-code-of-testcase.patch @@ -0,0 +1,864 @@ +From 95029b0ae49082d660330042c6c2becc9133124d Mon Sep 17 00:00:00 2001 +From: liubo +Date: Thu, 3 Mar 2022 10:25:08 +0800 +Subject: [PATCH 13/33] etmem: add code of testcase + +add code of testcase for etmem scan function +add code of testcase for etmem threadpool function +add code of testcase for etmem threadtimer function + +Signed-off-by: liubo +--- + .../etmem_scan_ops_export_llt_test/CMakeLists.txt | 26 ++ + .../etmem_scan_ops_export_llt.c | 279 +++++++++++++++++++++ + .../etmem_threadpool_ops_llt_test/CMakeLists.txt | 26 ++ + .../etmem_threadpool_ops_llt.c | 260 +++++++++++++++++++ + etmem/test/etmem_timer_ops_llt_test/CMakeLists.txt | 26 ++ + .../etmem_timer_ops_llt_test/etmem_timer_ops_llt.c | 183 ++++++++++++++ + 6 files changed, 800 insertions(+) + create mode 100644 etmem/test/etmem_scan_ops_export_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_scan_ops_export_llt_test/etmem_scan_ops_export_llt.c + create mode 100644 etmem/test/etmem_threadpool_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_threadpool_ops_llt_test/etmem_threadpool_ops_llt.c + create mode 100644 etmem/test/etmem_timer_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_timer_ops_llt_test/etmem_timer_ops_llt.c + +diff --git a/etmem/test/etmem_scan_ops_export_llt_test/CMakeLists.txt b/etmem/test/etmem_scan_ops_export_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..be68154 +--- /dev/null ++++ b/etmem/test/etmem_scan_ops_export_llt_test/CMakeLists.txt +@@ -0,0 +1,26 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: shikemeng ++# * Create: 2021-11-30 ++# * Description: CMakefileList for etmem_scan_ops_llt_test ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_scan_ops_export_llt) ++ ++add_executable(${EXE} etmem_scan_ops_export_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt libboundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_scan_ops_export_llt_test/etmem_scan_ops_export_llt.c b/etmem/test/etmem_scan_ops_export_llt_test/etmem_scan_ops_export_llt.c +new file mode 100644 +index 0000000..e8e6098 +--- /dev/null ++++ b/etmem/test/etmem_scan_ops_export_llt_test/etmem_scan_ops_export_llt.c +@@ -0,0 +1,279 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: yangkunlin ++ * Create: 2021-11-30 ++ * Description: test for the export scan library ++ ******************************************************************************/ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_scan_export.h" ++ ++/* normal init and exit */ ++static void test_etmem_exp_scan_001(void) ++{ ++ /* for test of exit without init*/ ++ etmemd_scan_exit(); ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ etmemd_scan_exit(); ++} ++ ++static void test_etmem_exp_scan_002(void) ++{ ++ /* for test of exit without init*/ ++ etmemd_scan_exit(); ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ /* init again before exit */ ++ CU_ASSERT_NOT_EQUAL(etmemd_scan_init(), 0); ++ etmemd_scan_exit(); ++} ++ ++static void check_vmas(struct vmas *vmas) ++{ ++ int i; ++ struct vma *curr_vma = NULL; ++ ++ CU_ASSERT_NOT_EQUAL(vmas->vma_cnt, 0); ++ ++ curr_vma = vmas->vma_list; ++ for (i = 0; i < vmas->vma_cnt; i++) { ++ CU_ASSERT_PTR_NOT_NULL(curr_vma); ++ curr_vma = curr_vma->next; ++ } ++} ++ ++/* test invalid get_vmas */ ++static void test_etmem_exp_scan_004(void) ++{ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ /* non-exist pid */ ++ vmas = etmemd_get_vmas("0", vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ /* pid is NULL */ ++ vmas = etmemd_get_vmas(NULL, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ /* pid contains invalid characters */ ++ vmas = etmemd_get_vmas("1-", vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ /* vmflags contains space */ ++ vmflags_array[0] = "r "; ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ /* vmflags length is not 2 */ ++ vmflags_array[0] = "rd "; ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ /* vmflags is NULL */ ++ vmflags_array[0] = NULL; ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NULL(vmas); ++ ++ /* test free is NULL */ ++ vmas = NULL; ++ etmemd_free_vmas(vmas); ++ ++ etmemd_scan_exit(); ++} ++ ++ ++/* test valid get_vmas */ ++static void test_etmem_exp_scan_003(void) ++{ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ struct vma *curr_vma = NULL; ++ int i; ++ ++ /* get vmas without init */ ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ etmemd_free_vmas(vmas); ++ ++ /* get vmas with init */ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ etmemd_free_vmas(vmas); ++ etmemd_scan_exit(); ++} ++ ++/* test invalid get_page_refs */ ++static void test_etmem_exp_scan_006(void) ++{ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ struct page_refs *page_refs = NULL; ++ int flags = SCAN_AS_HUGE | SCAN_IGN_HOST; ++ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ /* free null pointer */ ++ etmemd_free_page_refs(page_refs); ++ ++ /* vmas is NULL */ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), -1); ++ ++ /* vmas address range invalid*/ ++ vmas = (struct vmas *)calloc(1, sizeof(struct vmas)); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ vmas->vma_cnt = 1; ++ ++ struct vma *vma = (struct vma *)calloc(1, sizeof(struct vma)); ++ CU_ASSERT_PTR_NOT_NULL(vma); ++ vma->start = 0x0ff; ++ vma->end = 0x000; ++ vma->next = NULL; ++ vmas->vma_list = vma; ++ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), -1); ++ etmemd_free_vmas(vmas); ++ ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ ++ /* pid not exist */ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, "0", &page_refs, flags), -1); ++ CU_ASSERT_PTR_NULL(page_refs); ++ ++ /* pid is NULL */ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, NULL, &page_refs, flags), -1); ++ CU_ASSERT_PTR_NULL(page_refs); ++ ++ /* pid contains invalid chars */ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, "--", &page_refs, flags), -1); ++ CU_ASSERT_PTR_NULL(page_refs); ++ ++ etmemd_free_page_refs(page_refs); ++ etmemd_free_vmas(vmas); ++ etmemd_scan_exit(); ++} ++ ++/* test valid get_page_refs */ ++static void test_etmem_exp_scan_005(void) ++{ ++ CU_ASSERT_EQUAL(etmemd_scan_init(), 0); ++ ++ const char *pid = "1"; ++ char *vmflags_array[10] = {"rd"}; ++ int vmflag_num = 1; ++ int is_anon_only = false; ++ struct vmas *vmas = NULL; ++ struct page_refs *page_refs = NULL; ++ int flags = SCAN_AS_HUGE | SCAN_IGN_HOST; ++ ++ vmas = etmemd_get_vmas(pid, vmflags_array, vmflag_num, is_anon_only); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ check_vmas(vmas); ++ ++ CU_ASSERT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), 0); ++ CU_ASSERT_PTR_NOT_NULL(page_refs); ++ ++ etmemd_scan_exit(); ++ ++ /* get_page_refs after exit */ ++ CU_ASSERT_NOT_EQUAL(etmemd_get_page_refs(vmas, pid, &page_refs, flags), 0); ++ ++ etmemd_free_page_refs(page_refs); ++ etmemd_free_vmas(vmas); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_scan_ops_exp", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_etmem_exp_scan_001) == NULL || ++ CU_ADD_TEST(suite, test_etmem_exp_scan_002) == NULL || ++ CU_ADD_TEST(suite, test_etmem_exp_scan_003) == NULL || ++ CU_ADD_TEST(suite, test_etmem_exp_scan_004) == NULL || ++ CU_ADD_TEST(suite, test_etmem_exp_scan_005) == NULL || ++ CU_ADD_TEST(suite, test_etmem_exp_scan_006) == NULL) { ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_scan.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_threadpool_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_threadpool_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..cb084cf +--- /dev/null ++++ b/etmem/test/etmem_threadpool_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,26 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-11-30 ++# * Description: CMakefileList for etmem_threadpool_ops_llt_test ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_threadpool_ops_llt) ++ ++add_executable(${EXE} etmem_threadpool_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt libboundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_threadpool_ops_llt_test/etmem_threadpool_ops_llt.c b/etmem/test/etmem_threadpool_ops_llt_test/etmem_threadpool_ops_llt.c +new file mode 100644 +index 0000000..9917954 +--- /dev/null ++++ b/etmem/test/etmem_threadpool_ops_llt_test/etmem_threadpool_ops_llt.c +@@ -0,0 +1,260 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2020-08-13 ++ * Description: test for etmem threadpool operations ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_threadpool.h" ++#include "etmemd_pool_adapter.h" ++#include "etmemd_project.h" ++#include "etmemd_file.h" ++#include "etmemd_common.h" ++#include "etmemd_engine.h" ++#include "etmemd_slide.h" ++#include "etmemd_cslide.h" ++#include "securec.h" ++ ++#define ADD_WORKER_NUM 100 ++typedef void *(*add_worker_exector)(void *); ++ ++static struct task_executor g_test_exec; ++static int g_task_exe_time = 0; ++static struct engine_ops g_test_eng_ops = { ++ .alloc_pid_params = NULL, ++ .free_pid_params = NULL, ++}; ++ ++static void get_threadpool_create_num(int num, int exp) ++{ ++ thread_pool *pool = NULL; ++ ++ pool = threadpool_create(num); ++ CU_ASSERT_PTR_NOT_NULL(pool); ++ ++ CU_ASSERT_EQUAL(pool->max_thread_cap, exp); ++ threadpool_stop_and_destroy(&pool); ++} ++ ++static void test_threadpool_create(void) ++{ ++ int core = get_nprocs(); ++ ++ get_threadpool_create_num(1, 1); ++ get_threadpool_create_num(2, 2); ++ get_threadpool_create_num(2 * core, 2 * core); ++ get_threadpool_create_num(2 * core + 1, 2 * core + 1); ++ ++ threadpool_notify(NULL); ++ threadpool_reset_status(NULL); ++} ++ ++static void test_threadpool_delete(void) ++{ ++ thread_pool *pool = NULL; ++ threadpool_stop_and_destroy(&pool); ++ ++ pool = threadpool_create(1); ++ CU_ASSERT_PTR_NOT_NULL(pool); ++ ++ threadpool_stop_and_destroy(&pool); ++ CU_ASSERT_PTR_NULL(pool); ++} ++ ++static void *add_worker_fun(void *str) ++{ ++ char *temp_str = str; ++ printf("str: %s \n", temp_str); ++ return NULL; ++} ++ ++static unsigned int get_workerlist_num(const thread_pool *pool) ++{ ++ unsigned int num = 0; ++ thread_worker *worker = pool->worker_list; ++ ++ while (worker) { ++ num++; ++ worker = worker->next_node; ++ } ++ ++ return num; ++} ++ ++static void test_thpool_addwk_single(void) ++{ ++ char *args = "for add worker test.\n"; ++ thread_pool *pool = NULL; ++ add_worker_exector exector = add_worker_fun; ++ ++ pool = threadpool_create(1); ++ CU_ASSERT_PTR_NOT_NULL(pool); ++ ++ CU_ASSERT_EQUAL(threadpool_add_worker(pool, NULL, NULL), -1); ++ CU_ASSERT_EQUAL(threadpool_add_worker(pool, exector, NULL), -1); ++ CU_ASSERT_EQUAL(threadpool_add_worker(pool, NULL, args), -1); ++ CU_ASSERT_EQUAL(threadpool_add_worker(pool, exector, args), 0); ++ ++ CU_ASSERT_PTR_NOT_NULL(pool->worker_list); ++ CU_ASSERT_EQUAL(get_workerlist_num(pool), 1); ++ ++ threadpool_stop_and_destroy(&pool); ++ CU_ASSERT_PTR_NULL(pool); ++} ++ ++static void test_thpool_addwk_mul(void) ++{ ++ char *args = "for add worker test.\n"; ++ thread_pool *pool = NULL; ++ int add_num; ++ add_worker_exector exector = add_worker_fun; ++ ++ pool = threadpool_create(1); ++ CU_ASSERT_PTR_NOT_NULL(pool); ++ ++ for (add_num = 0; add_num < ADD_WORKER_NUM; add_num++) { ++ CU_ASSERT_EQUAL(threadpool_add_worker(pool, exector, args), 0); ++ } ++ ++ CU_ASSERT_PTR_NOT_NULL(pool->worker_list); ++ CU_ASSERT_EQUAL(__atomic_load_n(&pool->scheduing_size, __ATOMIC_SEQ_CST), ADD_WORKER_NUM); ++ ++ threadpool_stop_and_destroy(&pool); ++ CU_ASSERT_PTR_NULL(pool); ++} ++ ++static void init_thpool_objs(struct project *proj, struct engine *eng, struct task *tk) ++{ ++ proj->interval = 1; ++ proj->start = true; ++ proj->name = "test_project"; ++ eng->proj = proj; ++ eng->ops = &g_test_eng_ops; ++ tk->eng = eng; ++ tk->type = "pid"; ++ tk->value = "1"; ++ tk->max_threads = 10; ++} ++ ++static void test_thpool_start_error(void) ++{ ++ struct task tk; ++ struct engine eng; ++ struct project proj; ++ ++ init_thpool_objs(&proj, &eng, &tk); ++ ++ tk.max_threads = 0; ++ g_test_exec.tk = &tk; ++ ++ CU_ASSERT_EQUAL(start_threadpool_work(&g_test_exec), -1); ++} ++ ++static void *task_executor(void *arg) ++{ ++ g_task_exe_time++; ++ return NULL; ++} ++ ++static void test_thpool_start_stop(void) ++{ ++ struct task tk = {0}; ++ struct engine eng = {0}; ++ struct project proj = {0}; ++ ++ init_thpool_objs(&proj, &eng, &tk); ++ ++ g_test_exec.tk = &tk; ++ g_test_exec.func = task_executor; ++ ++ CU_ASSERT_EQUAL(start_threadpool_work(&g_test_exec), 0); ++ /* wait threadpool to work */ ++ sleep(2); ++ stop_and_delete_threadpool_work(&tk); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_threadpool_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_threadpool_create) == NULL || ++ CU_ADD_TEST(suite, test_threadpool_delete) == NULL || ++ CU_ADD_TEST(suite, test_thpool_addwk_single) == NULL || ++ CU_ADD_TEST(suite, test_thpool_addwk_mul) == NULL || ++ CU_ADD_TEST(suite, test_thpool_start_stop) == NULL || ++ CU_ADD_TEST(suite, test_thpool_start_error) == NULL) { ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_threadpool.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_timer_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_timer_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..76aa48e +--- /dev/null ++++ b/etmem/test/etmem_timer_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,26 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-11-30 ++# * Description: CMakefileList for etmem_timer_ops_llt_test ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_timer_ops_llt) ++ ++add_executable(${EXE} etmem_timer_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt libboundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_timer_ops_llt_test/etmem_timer_ops_llt.c b/etmem/test/etmem_timer_ops_llt_test/etmem_timer_ops_llt.c +new file mode 100644 +index 0000000..c97cdf9 +--- /dev/null ++++ b/etmem/test/etmem_timer_ops_llt_test/etmem_timer_ops_llt.c +@@ -0,0 +1,183 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2020-08-13 ++ * Description: test for etmem timer operations ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_threadtimer.h" ++ ++static int g_timer_exec_time = 0; ++ ++typedef void *(*timer_exector)(void *); ++ ++static void get_timer_expired_time(int time, int exp) ++{ ++ timer_thread *timer = NULL; ++ ++ timer = thread_timer_create(time); ++ CU_ASSERT_PTR_NOT_NULL(timer); ++ ++ CU_ASSERT_EQUAL(timer->expired_time, exp); ++ thread_timer_destroy(&timer); ++} ++ ++static void test_timer_create_delete(void) ++{ ++ timer_thread *timer = NULL; ++ thread_timer_destroy(&timer); ++ ++ get_timer_expired_time(1, 1); ++ get_timer_expired_time(2, 2); ++ get_timer_expired_time(50, 50); ++ get_timer_expired_time(1199, 1199); ++ get_timer_expired_time(1201, 1201); ++} ++ ++static void *threadtimer_exector(void *str) ++{ ++ char *temp_str = str; ++ printf("threadtimer_exector: %s\n", temp_str); ++ g_timer_exec_time++; ++ return NULL; ++} ++ ++static void test_timer_start_error(void) ++{ ++ char *timer_args = "for timer start test.\n"; ++ timer_exector exector = threadtimer_exector; ++ timer_thread *timer = NULL; ++ ++ timer = thread_timer_create(60); ++ CU_ASSERT_PTR_NOT_NULL(timer); ++ ++ CU_ASSERT_EQUAL(thread_timer_start(NULL, NULL, NULL), -1); ++ CU_ASSERT_EQUAL(thread_timer_start(timer, NULL, NULL), -1); ++ CU_ASSERT_EQUAL(thread_timer_start(timer, exector, NULL), -1); ++ CU_ASSERT_EQUAL(thread_timer_start(timer, NULL, timer_args), -1); ++ CU_ASSERT_EQUAL(thread_timer_start(timer, exector, timer_args), 0); ++ CU_ASSERT_FALSE(timer->down); ++ CU_ASSERT_EQUAL(thread_timer_start(timer, exector, timer_args), 0); ++ ++ thread_timer_destroy(&timer); ++ thread_timer_stop(timer); ++} ++ ++static void test_timer_start_ok(void) ++{ ++ char *timer_args = "for timer start test.\n"; ++ timer_exector exector = threadtimer_exector; ++ timer_thread *timer = NULL; ++ ++ timer = thread_timer_create(1); ++ CU_ASSERT_PTR_NOT_NULL(timer); ++ ++ CU_ASSERT_EQUAL(thread_timer_start(timer, exector, timer_args), 0); ++ CU_ASSERT_FALSE(timer->down); ++ ++ sleep(2); ++ CU_ASSERT_NOT_EQUAL(g_timer_exec_time, 0); ++ ++ thread_timer_stop(timer); ++ thread_timer_destroy(&timer); ++} ++ ++static void test_timer_stop(void) ++{ ++ char *timer_args = "for timer start test.\n"; ++ timer_exector exector = threadtimer_exector; ++ timer_thread *timer = NULL; ++ ++ thread_timer_stop(timer); ++ ++ timer = thread_timer_create(60); ++ CU_ASSERT_PTR_NOT_NULL(timer); ++ ++ CU_ASSERT_EQUAL(thread_timer_start(timer, exector, timer_args), 0); ++ CU_ASSERT_FALSE(timer->down); ++ ++ thread_timer_stop(timer); ++ CU_ASSERT_TRUE(timer->down); ++ thread_timer_destroy(&timer); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_timer_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_timer_create_delete) == NULL || ++ CU_ADD_TEST(suite, test_timer_start_error) == NULL || ++ CU_ADD_TEST(suite, test_timer_start_ok) == NULL || ++ CU_ADD_TEST(suite, test_timer_stop) == NULL) { ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_threadtimer.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +-- +1.8.3.1 + diff --git a/0064-etmem-add-code-of-testcase.patch b/0064-etmem-add-code-of-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d278bb5d6293b4ea6c7b8e8cd5d51e39585ebe1 --- /dev/null +++ b/0064-etmem-add-code-of-testcase.patch @@ -0,0 +1,1202 @@ +From 51adb91840286ce1720a43ac7d756fa7d4e6234e Mon Sep 17 00:00:00 2001 +From: liubo +Date: Mon, 24 Jan 2022 01:34:44 +0800 +Subject: [PATCH 14/33] etmem: add code of testcase + +add code of testcase for etmem slide engine functions +and add conf file for test use. + +Signed-off-by: liubo +--- + etmem/test/conf/conf_cslide/eng.config | 7 + + etmem/test/conf/conf_cslide/proj.config | 5 + + etmem/test/conf/conf_cslide/task.config | 9 + + etmem/test/conf/conf_slide/config_file | 18 + + etmem/test/etmem_slide_ops_llt_test/CMakeLists.txt | 29 + + .../etmem_slide_ops_llt_test/etmem_slide_ops_llt.c | 648 +++++++++++++++++++++ + etmem/test/etmem_slide_ops_llt_test/mem_swaptest.c | 95 +++ + .../etmem_slide_ops_llt_test/test_slide_ops.sh | 309 ++++++++++ + 8 files changed, 1120 insertions(+) + create mode 100644 etmem/test/conf/conf_cslide/eng.config + create mode 100644 etmem/test/conf/conf_cslide/proj.config + create mode 100644 etmem/test/conf/conf_cslide/task.config + create mode 100644 etmem/test/conf/conf_slide/config_file + create mode 100644 etmem/test/etmem_slide_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_slide_ops_llt_test/etmem_slide_ops_llt.c + create mode 100644 etmem/test/etmem_slide_ops_llt_test/mem_swaptest.c + create mode 100644 etmem/test/etmem_slide_ops_llt_test/test_slide_ops.sh + +diff --git a/etmem/test/conf/conf_cslide/eng.config b/etmem/test/conf/conf_cslide/eng.config +new file mode 100644 +index 0000000..4d0665b +--- /dev/null ++++ b/etmem/test/conf/conf_cslide/eng.config +@@ -0,0 +1,7 @@ ++[engine] ++name=cslide ++project=test ++node_pair=2,0;3,1 ++hot_threshold=1 ++node_mig_quota=256 ++node_hot_reserve=119600 +\ No newline at end of file +diff --git a/etmem/test/conf/conf_cslide/proj.config b/etmem/test/conf/conf_cslide/proj.config +new file mode 100644 +index 0000000..1174df3 +--- /dev/null ++++ b/etmem/test/conf/conf_cslide/proj.config +@@ -0,0 +1,5 @@ ++[project] ++name=test ++loop=3 ++interval=1 ++sleep=1 +\ No newline at end of file +diff --git a/etmem/test/conf/conf_cslide/task.config b/etmem/test/conf/conf_cslide/task.config +new file mode 100644 +index 0000000..336be39 +--- /dev/null ++++ b/etmem/test/conf/conf_cslide/task.config +@@ -0,0 +1,9 @@ ++[task] ++project=test ++engine=cslide ++name=background1 ++type=pid ++value=1 ++vm_flags=ht ++anon_only=no ++ign_host=yes +\ No newline at end of file +diff --git a/etmem/test/conf/conf_slide/config_file b/etmem/test/conf/conf_slide/config_file +new file mode 100644 +index 0000000..5d9f965 +--- /dev/null ++++ b/etmem/test/conf/conf_slide/config_file +@@ -0,0 +1,18 @@ ++[project] ++name=test ++loop=1 ++interval=1 ++sleep=1 ++ ++[engine] ++name=slide ++project=test ++ ++[task] ++project=test ++engine=slide ++name=background1 ++type=name ++value=sshd ++max_threads=10 ++T=2 +diff --git a/etmem/test/etmem_slide_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_slide_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..2162d9e +--- /dev/null ++++ b/etmem/test/etmem_slide_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,29 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-11-29 ++# * Description: CMakefileList for etmem_slide_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(../common) ++INCLUDE_DIRECTORIES(../../src/etmemd_src) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_slide_ops_llt) ++ ++add_executable(${EXE} etmem_slide_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so ${BUILD_DIR}/lib/libtest.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) ++target_link_libraries(mem_swaptest pthread dl rt boundscheck) +diff --git a/etmem/test/etmem_slide_ops_llt_test/etmem_slide_ops_llt.c b/etmem/test/etmem_slide_ops_llt_test/etmem_slide_ops_llt.c +new file mode 100644 +index 0000000..3a04a86 +--- /dev/null ++++ b/etmem/test/etmem_slide_ops_llt_test/etmem_slide_ops_llt.c +@@ -0,0 +1,648 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-11-29 ++ * Description: This is a source file of the unit test for project-related commands in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_project.h" ++#include "etmemd_task.h" ++#include "etmemd_engine.h" ++#include "etmemd_slide.h" ++#include "etmemd_cslide.h" ++#include "etmemd_rpc.h" ++#include "securec.h" ++ ++#include "test_common.h" ++ ++#include "etmemd_slide.c" ++ ++#define PID_STR_MAX_LEN 10 ++#define PID_TEST_NUM 100 ++#define PID_PROCESS_MEM 5000 ++#define PID_PROCESS_SLEEP_TIME 60 ++#define WATER_LINT_TEMP 3 ++#define RAND_STR_ARRAY_LEN 62 ++ ++static void test_engine_name_invalid(void) ++{ ++ struct eng_test_param slide_param; ++ GKeyFile *config = NULL; ++ ++ init_slide_eng(&slide_param); ++ ++ slide_param.name = "engine no exist"; ++ config = construct_eng_config(&slide_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++ ++ slide_param.name = ""; ++ config = construct_eng_config(&slide_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++ ++ slide_param.name = NULL; ++ config = construct_eng_config(&slide_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++} ++ ++static void test_engine_proj_invalid(void) ++{ ++ struct eng_test_param slide_param; ++ GKeyFile *config = NULL; ++ ++ init_slide_eng(&slide_param); ++ ++ slide_param.proj = "proj no exist"; ++ config = construct_eng_config(&slide_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_PRO_NOEXIST); ++ destroy_eng_config(config); ++ ++ slide_param.proj = ""; ++ config = construct_eng_config(&slide_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++ ++ slide_param.proj = NULL; ++ config = construct_eng_config(&slide_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++} ++ ++void test_etmem_slide_engine_002(void) ++{ ++ struct proj_test_param proj_param; ++ struct eng_test_param slide_eng; ++ struct cslide_eng_test_param cslide_eng; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(&proj_param); ++ do_add_proj_test(&proj_param); ++ ++ init_cslide_eng(&cslide_eng); ++ config = construct_cslide_eng_config(&cslide_eng); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_cslide_eng_config(config); ++ ++ /* repeat add and remove engine */ ++ init_slide_eng(&slide_eng); ++ config = construct_eng_config(&slide_eng); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_ENG_EXISTED); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_ENG_NOEXIST); ++ destroy_eng_config(config); ++ ++ test_engine_name_invalid(); ++ test_engine_proj_invalid(); ++ ++ init_cslide_eng(&cslide_eng); ++ config = construct_cslide_eng_config(&cslide_eng); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_SUCCESS); ++ destroy_cslide_eng_config(config); ++ ++ do_rm_proj_test(&proj_param); ++} ++ ++void test_etmem_slide_engine_001(void) ++{ ++ struct proj_test_param proj_param; ++ struct eng_test_param slide_eng; ++ struct slide_task_test_param slide_task; ++ GKeyFile *eng_config = NULL; ++ GKeyFile *task_config = NULL; ++ ++ init_proj_param(&proj_param); ++ do_add_proj_test(&proj_param); ++ ++ init_slide_eng(&slide_eng); ++ eng_config = construct_eng_config(&slide_eng); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ ++ init_slide_task(&slide_task); ++ task_config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_SUCCESS); ++ destroy_slide_task_config(task_config); ++ ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(eng_config), OPT_SUCCESS); ++ destroy_eng_config(eng_config); ++ ++ do_rm_proj_test(&proj_param); ++} ++ ++static void task_test_init(void) ++{ ++ struct proj_test_param proj_param; ++ struct eng_test_param eng_param; ++ struct cslide_eng_test_param cslide_eng; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(&proj_param); ++ do_add_proj_test(&proj_param); ++ ++ init_cslide_eng(&cslide_eng); ++ config = construct_cslide_eng_config(&cslide_eng); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_cslide_eng_config(config); ++ ++ init_slide_eng(&eng_param); ++ config = construct_eng_config(&eng_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++} ++ ++static void task_test_fini(void) ++{ ++ struct proj_test_param proj_param; ++ struct eng_test_param eng_param; ++ struct cslide_eng_test_param cslide_eng; ++ GKeyFile *config = NULL; ++ ++ init_cslide_eng(&cslide_eng); ++ config = construct_cslide_eng_config(&cslide_eng); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_SUCCESS); ++ destroy_cslide_eng_config(config); ++ ++ init_slide_eng(&eng_param); ++ config = construct_eng_config(&eng_param); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_SUCCESS); ++ destroy_eng_config(config); ++ ++ init_proj_param(&proj_param); ++ do_rm_proj_test(&proj_param); ++} ++ ++static void test_etmem_slide_task_001(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ ++ task_test_init(); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task1"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task2"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task1"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task2"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ task_test_fini(); ++} ++ ++static void test_etmem_task_swap_flag_error(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ ++ task_test_init(); ++ ++ /* empty value of swap_flag */ ++ init_slide_task(&slide_task); ++ slide_task.swap_flag = ""; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of swap_flag */ ++ init_slide_task(&slide_task); ++ slide_task.swap_flag = "wrong"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of swap_flag */ ++ init_slide_task(&slide_task); ++ slide_task.swap_flag = "YES"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of swap_flag */ ++ init_slide_task(&slide_task); ++ slide_task.swap_flag = "NO"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of pid which is equal to 0 */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.value = "0"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ /* sleep 10 seconds to run etmemd project for coverage of slide_executor */ ++ sleep(10); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* run slide_policy_interface fail */ ++ CU_ASSERT_EQUAL(slide_policy_interface(NULL, NULL), NULL); ++ ++ /* run slide_do_migrate fail */ ++ CU_ASSERT_EQUAL(slide_do_migrate(1, NULL), -1); ++ ++ task_test_fini(); ++} ++ ++static void test_etmem_task_swap_flag_ok(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ ++ task_test_init(); ++ ++ /* empty value of swap_flag */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task1_swap_flag_yes"; ++ slide_task.swap_flag = "yes"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task1_swap_flag_no"; ++ slide_task.swap_flag = "no"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ task_test_fini(); ++} ++ ++static void test_etmem_task_swap_threshold_error(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ ++ task_test_init(); ++ ++ /* empty value of swap_threshold */ ++ init_slide_task(&slide_task); ++ slide_task.swap_threshold = ""; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* swap_threshold too long */ ++ init_slide_task(&slide_task); ++ slide_task.swap_threshold = "12345678910234g"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* swap_threshold para is wrong*/ ++ init_slide_task(&slide_task); ++ slide_task.swap_threshold = "12hhG"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* swap_threshold para is wrong*/ ++ init_slide_task(&slide_task); ++ slide_task.swap_threshold = "1234"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of pid which is equal to 0 */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.value = "0"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ /* sleep 10 seconds to run etmemd project for coverage of slide_executor */ ++ sleep(10); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* run slide_policy_interface fail */ ++ CU_ASSERT_EQUAL(slide_policy_interface(NULL, NULL), NULL); ++ ++ /* run slide_do_migrate fail */ ++ CU_ASSERT_EQUAL(slide_do_migrate(1, NULL), -1); ++ ++ task_test_fini(); ++} ++ ++static void test_etmem_task_swap_threshold_ok(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ ++ task_test_init(); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task1_swap_threshold_5G"; ++ slide_task.swap_threshold = "5G"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task1_swap_threshold_5g"; ++ slide_task.swap_threshold = "5g"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task2_swap_threshold"; ++ slide_task.swap_threshold = "123456789g"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = "task3_swap_threshold"; ++ slide_task.swap_threshold = "999999999g"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ task_test_fini(); ++} ++ ++static void test_task_common_invalid_config(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ char *long_name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; ++ ++ /* repeat add */ ++ init_slide_task(&slide_task); ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_TASK_EXISTED); ++ destroy_slide_task_config(config); ++ ++ /* no exist remove */ ++ slide_task.task_param.name = "task no exists"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_TASK_NOEXIST); ++ destroy_slide_task_config(config); ++ ++ /* repeat remove */ ++ init_slide_task(&slide_task); ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_TASK_NOEXIST); ++ destroy_slide_task_config(config); ++ ++ /* no project exist */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.proj = "proj no exists"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_PRO_NOEXIST); ++ destroy_slide_task_config(config); ++ ++ /* not project set */ ++ slide_task.task_param.proj = NULL; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_INVAL); ++ destroy_slide_task_config(config); ++ ++ /* long project name */ ++ slide_task.task_param.proj = long_name; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_INVAL); ++ destroy_slide_task_config(config); ++ ++ /* no engine exist */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.eng = "task no exists"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_ENG_NOEXIST); ++ destroy_slide_task_config(config); ++ ++ /* no engine set */ ++ slide_task.task_param.eng = NULL; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_INVAL); ++ destroy_slide_task_config(config); ++ ++ /* long engine name */ ++ slide_task.task_param.eng = long_name; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_INVAL); ++ destroy_slide_task_config(config); ++ ++ /* no name set for task */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.name = NULL; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_INVAL); ++ destroy_slide_task_config(config); ++ ++ /* task name too long */ ++ slide_task.task_param.name = long_name; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_INVAL); ++ destroy_slide_task_config(config); ++ ++ /* type invalid */ ++ init_slide_task(&slide_task); ++ slide_task.task_param.type = "invalid"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++} ++ ++static void test_task_slide_invalid_config(void) ++{ ++ struct slide_task_test_param slide_task; ++ GKeyFile *config = NULL; ++ ++ init_slide_task(&slide_task); ++ ++ /* enpty value of T */ ++ slide_task.T = ""; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of T which is bigger than WEIGHT * loop times */ ++ slide_task.T = "10"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of T which is less than 0 */ ++ slide_task.T = "-1"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ /* wrong value of max_threads which is equal to 0, slide will correct it ++ * to valid value ++ */ ++ slide_task.max_threads = "0"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of max_threads which is equal to -1, slide will correct it ++ * to valid value ++ */ ++ slide_task.max_threads = "-1"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* wrong value of max_threads which is too big, slide will correct it ++ * to valid value ++ */ ++ slide_task.max_threads = "10000"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ init_slide_task(&slide_task); ++ /* wrong value of pid which is equal to 0 */ ++ slide_task.task_param.value = "0"; ++ config = construct_slide_task_config(&slide_task); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ /* sleep 10 seconds to run etmemd project for coverage of slide_executor */ ++ sleep(10); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(config), OPT_SUCCESS); ++ destroy_slide_task_config(config); ++ ++ /* run slide_policy_interface fail */ ++ CU_ASSERT_EQUAL(slide_policy_interface(NULL, NULL), NULL); ++ ++ /* run slide_do_migrate fail */ ++ CU_ASSERT_EQUAL(slide_do_migrate(1, NULL), -1); ++} ++ ++void test_etmem_slide_task_002(void) ++{ ++ task_test_init(); ++ ++ test_task_common_invalid_config(); ++ test_task_slide_invalid_config(); ++ ++ task_test_fini(); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++static void test_slide(void) ++{ ++ CU_ASSERT_EQUAL(system("../etmem_slide_ops_llt_test/test_slide_ops.sh"), 0); ++} ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_slide_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_etmem_slide_task_002) == NULL || ++ CU_ADD_TEST(suite, test_etmem_slide_task_001) == NULL || ++ CU_ADD_TEST(suite, test_etmem_slide_engine_002) == NULL || ++ CU_ADD_TEST(suite, test_etmem_slide_engine_001) == NULL || ++ CU_ADD_TEST(suite, test_etmem_task_swap_flag_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_task_swap_flag_ok) == NULL || ++ CU_ADD_TEST(suite, test_etmem_task_swap_threshold_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_task_swap_threshold_ok) == NULL || ++ CU_ADD_TEST(suite, test_slide) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_slide.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_slide_ops_llt_test/mem_swaptest.c b/etmem/test/etmem_slide_ops_llt_test/mem_swaptest.c +new file mode 100644 +index 0000000..ab26f8e +--- /dev/null ++++ b/etmem/test/etmem_slide_ops_llt_test/mem_swaptest.c +@@ -0,0 +1,95 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-11-29 ++ * Description: construct a progress test for etmemd slide engine ++ ******************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "securec.h" ++ ++#define VMA_FLAG 203 ++#define SLEEP_TIME 2 ++ ++int main(int argc, char *argv[]) ++{ ++ char *memory_with_flag = NULL; ++ char *memory_no_flag = NULL; ++ char i = 0; ++ int ret = -1; ++ /* get memory size: 1GB for test */ ++ size_t memory_len = (1UL * 1024) * 1024 * 1024; ++ ++ memory_with_flag = (char *)mmap(NULL, memory_len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (memory_with_flag == MAP_FAILED) { ++ perror("map mem"); ++ memory_with_flag = NULL; ++ return -1; ++ } ++ ++ ret = madvise(memory_with_flag, memory_len, VMA_FLAG); ++ if (ret != 0) { ++ printf("madvise error.\n"); ++ goto free_memory_with_flag; ++ } ++ ++ ret = memset_s(memory_with_flag, memory_len, '0', memory_len); ++ if (ret != EOK) { ++ printf("memset for memory_with flag fail, ret: %d err(%s)\n", ret, strerror(errno)); ++ goto free_memory_with_flag; ++ } ++ ++ memory_no_flag = (char *)mmap(NULL, memory_len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (memory_no_flag == MAP_FAILED) { ++ perror("map mem"); ++ goto free_memory_with_flag; ++ } ++ ++ ret = memset_s(memory_no_flag, memory_len, '0', memory_len); ++ if (ret != EOK) { ++ printf("memset for memory_no_flag flag fail, ret: %d err(%s)\n", ret, strerror(errno)); ++ goto free_all_memory; ++ } ++ ++ while (1) { ++ ret = memset_s(memory_no_flag, memory_len, i, memory_len); ++ if (ret != EOK) { ++ printf("memset for memory_no_flag flag fail\n"); ++ goto free_all_memory; ++ } ++ ++ sleep(SLEEP_TIME); ++ i++; ++ } ++ ++free_all_memory: ++ ret = munmap(memory_no_flag, memory_len); ++ if (ret != 0) { ++ printf("release memory for memory_no_flag failed.\n"); ++ return -1; ++ } ++ ++free_memory_with_flag: ++ ret = munmap(memory_with_flag, memory_len); ++ if (ret != 0) { ++ printf("release memory for memory_with_flag failed.\n"); ++ return -1; ++ } ++ ++ return 0; ++} +diff --git a/etmem/test/etmem_slide_ops_llt_test/test_slide_ops.sh b/etmem/test/etmem_slide_ops_llt_test/test_slide_ops.sh +new file mode 100644 +index 0000000..f763726 +--- /dev/null ++++ b/etmem/test/etmem_slide_ops_llt_test/test_slide_ops.sh +@@ -0,0 +1,309 @@ ++#!/bin/bash ++# ++#Level: 0 ++#Type: auto ++#Description: start 多个不同的project ++ ++set +e ++ ++config_file="../conf/conf_slide/config_file" ++config_file_bak="../conf/conf_slide/config_file_bak" ++Etmem_slide_test="slide_test" ++project_configfile=`pwd`/"slide_project_swap_test.yaml" ++task_configfile=`pwd`/"slide_task_test.yaml" ++ ++function rand_file_Str ++{ ++ j=0; ++ for i in {a..z};do array[$j]=$i;j=$(($j+1));done ++ for i in {A..Z};do array[$j]=$i;j=$(($j+1));done ++ for ((i=0;i<257;i++));do filestrs="$filestrs${array[$(($RANDOM%$j))]}";done ++} ++ ++function rand_pro_Str ++{ ++ j=0; ++ for i in {a..z};do array[$j]=$i;j=$(($j+1));done ++ for i in {A..Z};do array[$j]=$i;j=$(($j+1));done ++ for ((i=0;i<33;i++));do prostrs="$prostrs${array[$(($RANDOM%$j))]}";done ++} ++ ++function rand_sock_Str ++{ ++ j=0; ++ for i in {a..z};do array[$j]=$i;j=$(($j+1));done ++ for i in {A..Z};do array[$j]=$i;j=$(($j+1));done ++ for ((i=0;i<108;i++));do sockstrs="$sockstrs${array[$(($RANDOM%$j))]}";done ++} ++ ++function add_project() ++{ ++ touch $project_configfile ++ ++ echo "[project]" >> $project_configfile ++ echo "name=$Etmem_slide_test" >> $project_configfile ++ echo "loop=1" >> $project_configfile ++ echo "interval=1" >> $project_configfile ++ echo "sleep=1" >> $project_configfile ++ ++ echo "sysmem_threshold=100" >> $project_configfile ++ echo "swapcache_high_wmark=3" >> $project_configfile ++ echo "swapcache_low_wmark=1" >> $project_configfile ++ ++ echo "" >> $project_configfile ++ echo "#slide" >> $project_configfile ++ echo "[engine]" >> $project_configfile ++ echo "name=slide" >> $project_configfile ++ echo "project=$Etmem_slide_test" >> $project_configfile ++ ++ ./bin/etmem obj add -f ${project_configfile} -s sock_slide_name ++ ++ for i in $* ++ do ++ rm -f $task_configfile ++ touch $task_configfile ++ echo "[task]" >> $task_configfile ++ echo "project=$Etmem_slide_test" >> $task_configfile ++ echo "engine=slide" >> $task_configfile ++ echo "name=swap_test_$i" >> $task_configfile ++ echo "type=name" >> $task_configfile ++ echo "value = $i" >> $task_configfile ++ echo "max_threads=1" >> $task_configfile ++ echo "T=3" >> $task_configfile ++ echo $i ++ if [ $i = 'mem_swaptest' ];then ++ echo "swap_threshold=1g" >> $task_configfile ++ echo "swap_flag=yes" >> $task_configfile ++ fi ++ ./bin/etmem obj add -f ${task_configfile} -s sock_slide_name ++ done ++} ++ ++function start_project() ++{ ++ ./bin/etmem project start -n ${Etmem_slide_test} -s sock_slide_name ++ ./bin/etmem project show -s sock_slide_name ++} ++ ++function project_name_length_larger() ++{ ++ sed -i "s/name=test/name=project_name_length_larger_than_32/g" ${config_file_bak} ++} ++ ++function project_name_length_restore() ++{ ++ sed -i "s/name=project_name_length_larger_than_32/name=test/g" ${config_file_bak} ++} ++ ++cmd_test() ++{ ++ ./bin/etmem ++ ./bin/etmem -h ++ ./bin/etmem help ++ ./bin/etmem project ++ ./bin/etmem obj ++ ./bin/etmem project -h ++ ./bin/etmem obj -h ++ ./bin/etmem project help ++ ./bin/etmem obj help ++ ./bin/etmem project other ++ ./bin/etmem obj other ++ ./bin/etmem obj add ++ ./bin/etmem obj add -o other ++ ./bin/etmem project start -o other ++ ./bin/etmem project start -n project_name_length_larger_than_32 ++ project_name_length_larger ++ ./bin/etmem obj add -f ${config_file_bak} -s sock_slide_name ++ project_name_length_restore ++ ./bin/etmem obj add -s sock_cmd_name ++ ./bin/etmem obj add -f ${config_file} ++ ./bin/etmem obj add -f ${config_file} -s sock_cmd_name ++ ./bin/etmem obj add -f ${filestrs} -s sock_cmd_name ++ ./bin/etmem obj add -n ${prostrs} -s sock_cmd_name ++ ./bin/etmem obj add -f ${config_file} -s ${sockstrs} ++ ./bin/etmem obj add -f ${config_file} -s sock_cmd_name error ++ ./bin/etmem project start -n ${Etmem_slide_test} -s sock_cmd_name ++ ./bin/etmem project start -n ${Etmem_slide_test} ++ ./bin/etmem project start -s sock_cmd_name ++ ./bin/etmem engine ++ ./bin/etmem engine -h ++ ./bin/etmem engine --help ++ ./bin/etmem engine -s "" ++ ./bin/etmem engine -s sock_name ++ ./bin/etmem engine -s sock_name -n "" ++ ./bin/etmem engine -s sock_name -n proj_name ++ ./bin/etmem engine -s sock_name -n proj_name -e "" -t task_name ++ ./bin/etmem engine -s sock_name -n proj_name -e cslide -t "" ++ ./bin/etmem engine "" -s sock_name -n proj_name -e cslide -t task_name ++ ./bin/etmem engine showtaskpages -s sock_name ++ ./bin/etmem engine showtaskpages -s sock_name -n proj_name ++ ./bin/etmem engine showtaskpages -s sock_name -n proj_name -e ++ ./bin/etmem engine showtaskpages -s sock_name -n proj_name -e cslide ++ ./bin/etmem engine showtaskpages -s sock_name -n proj_name -e cslide -t task_name ++ ./bin/etmem engine showtaskpages -s sock_name -n proj_name -e slide -t task_name ++ ./bin/etmem engine showhostpages -s sock_name -n proj_name -e cslide -t task_name ++ ./bin/etmem engine showhostpages -s sock_name -n proj_name -e cslide -t "" ++ ./bin/etmemd error ++ ./bin/etmemd -s ++ ./bin/etmemd -h ++ ./bin/etmemd -l a ++ ./bin/etmemd ++ ./bin/etmemd -m ++ ./bin/etmemd -m A ++ ./bin/etmemd -h help ++ ./bin/etmemd -s test_socket socket ++ ./bin/etmemd -l 0 -s sock_slide_name & ++ sleep 1 ++ ./bin/etmem engine shownothing -n proj_name -e cslide -t task_name -s sock_slide_name ++ killall etmemd ++} ++ ++pre_test() ++{ ++ echo "keep the param_val unchanged" ++ cp ${config_file} ${config_file_bak} ++ if [ ! -d ./../build ];then ++ echo -e " directory \033[;31mnot exist\033[0m, pls check!" ++ exit 1; ++ fi ++ rm -f $project_configfile ++ cp ./bin/mem_swaptest ./bin/sysmem_swaptest ++ ./bin/mem_swaptest & ++ ./bin/sysmem_swaptest & ++} ++ ++do_test() ++{ ++ touch etmemd.log ++ ./bin/etmemd -l 0 -s sock_slide_name >etmemd.log 2>&1 & ++ sleep 1 ++ ++ add_project $1 $2 & ++ pidadd_project=$! ++ wait ${pidadd_project} ++ ++ echo "" ++ echo "start to test slide of etmemd" ++ ++ start_project & ++ pidstart_project=$! ++ wait ${pidstart_project} ++ ++ sleep 20 ++} ++ ++post_test() ++{ ++ pid_swap_test=`pidof mem_swaptest` ++ echo ${pid_swap_test} ++ pid_sysmem_swaptest=`pidof sysmem_swaptest` ++ echo ${pid_sysmem_swaptest} ++ mem_vmswap=$(cat /proc/${pid_swap_test}/status |grep VmSwap |awk '{print $2}') ++ echo ${mem_vmswap} ++ ++ kill -9 ${pid_swap_test} ++ kill -9 ${pid_sysmem_swaptest} ++ ++ echo "now to recover env" ++ rm -f ${config_file_bak} ++ rm -rf etmemd.log ++ killall etmemd ++} ++ ++test_empty_config() ++{ ++ ./bin/etmemd -l 0 -s dt_socket & ++ etmemd_pid=$! ++ sleep 1 ++ echo "[not_used_group]" > ../conf/conf_slide/empty_config ++ echo "aaa=bbb" >> ../conf/conf_slide/empty_config ++ ./bin/etmem obj add -f ../conf/conf_slide/empty_config -s dt_socket ++ if [ "$?" == "0" ];then ++ echo "add empty config success unexpected" ++ exit 1 ++ fi ++ ps -aux |grep -v grep |grep ${etmemd_pid} ++ if [ "$?" != "0" ];then ++ echo "etmemd exit unexpected after add empty config" ++ exit 1 ++ fi ++ killall etmemd ++ rm -f ../conf/conf_slide/empty_config ++} ++ ++test_error_config() ++{ ++ echo "[task]" > ../conf/error_proj.config ++ echo "type=xxxxx" >> ../conf/error_proj.config ++ ++ ./bin/etmemd -l 0 -s dt_socket & ++ etmemd_pid=$! ++ sleep 1 ++ ./bin/etmem obj del -f ../conf/error_proj.config -s dt_socket ++ if [ "$?" == "0" ];then ++ echo "add error config success unexpected" ++ exit 1 ++ fi ++ ps -aux |grep -v grep |grep ${etmemd_pid} ++ if [ "$?" != "0" ];then ++ echo "etmemd exit unexpected after add error config" ++ exit 1 ++ fi ++ killall etmemd ++ rm -f ../conf/error_proj.config ++} ++ ++test_noexist_config() ++{ ++ ./bin/etmemd -l 0 -s dt_socket & ++ etmemd_pid=$! ++ sleep 1 ++ ./bin/etmem obj add -f ../conf/noexist.config -s dt_socket ++ if [ "$?" == "0" ];then ++ echo "add noexist config success unexpected" ++ exit 1 ++ fi ++ ps -aux |grep -v grep |grep ${etmemd_pid} ++ if [ "$?" != "0" ];then ++ echo "etmemd exit unexpected after add noexist config" ++ exit 1 ++ fi ++ killall etmemd ++} ++ ++test_sig_pipe() ++{ ++ ./bin/etmemd -l 0 -s dt_socket & ++ etmemd_pid=$! ++ sleep 1 ++ kill -13 ${etmemd_pid} ++ ps -aux |grep -v grep |grep ${etmemd_pid} ++ if [ "$?" != "0" ];then ++ echo "etmemd exit unexpected after recv SIGPIPE" ++ exit 1 ++ fi ++ killall etmemd ++} ++ ++test_etmem_help() ++{ ++ ./bin/etmem help ++ if [ "$?" != "0" ];then ++ echo "etmem help return error unexpect" ++ exit 1 ++ fi ++} ++ ++rand_file_Str ++rand_pro_Str ++rand_sock_Str ++cmd_test ++pre_test ++do_test mem_swaptest sysmem_swaptest ++post_test ++ ++test_sig_pipe ++test_empty_config ++test_error_config ++test_noexist_config ++test_etmem_help +-- +1.8.3.1 + diff --git a/0065-etmem-add-code-of-testcase.patch b/0065-etmem-add-code-of-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..8db85c9e75df46e46746f753e1c1c3765c83dfcd --- /dev/null +++ b/0065-etmem-add-code-of-testcase.patch @@ -0,0 +1,682 @@ +From 9018988c20ce1ee49d2d4458d85b72993ee39283 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Mon, 24 Jan 2022 03:02:41 +0800 +Subject: [PATCH 15/33] etmem: add code of testcase + +add code of testcase for etmem migrate functions +add testcase to etmem project function + +Signed-off-by: liubo +--- + etmem/test/common/test_common.c | 33 ++- + etmem/test/common/test_common.h | 72 ++++--- + etmem/test/etmem_migrate_ops_llt/CMakeLists.txt | 27 +++ + .../etmem_migrate_ops_llt/etmem_migrate_ops_llt.c | 226 +++++++++++++++++++++ + .../etmem_project_ops_llt.c | 161 ++++++++++++++- + .../etmem_scan_ops_llt_test/etmem_scan_ops_llt.c | 4 +- + 6 files changed, 484 insertions(+), 39 deletions(-) + create mode 100644 etmem/test/etmem_migrate_ops_llt/CMakeLists.txt + create mode 100644 etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c + +diff --git a/etmem/test/common/test_common.c b/etmem/test/common/test_common.c +index 4551177..4bd3fc3 100644 +--- a/etmem/test/common/test_common.c ++++ b/etmem/test/common/test_common.c +@@ -63,6 +63,18 @@ void construct_proj_file(struct proj_test_param *param) + if (param->sleep != NULL) { + CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SLEEP, param->sleep), -1); + } ++ if (param->sysmem_threshold != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SYSMEM_THRESHOLD, ++ param->sysmem_threshold), -1); ++ } ++ if (param->swapcache_high_wmark != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SWAPCACHE_HIGH_WMARK, ++ param->swapcache_high_wmark), -1); ++ } ++ if (param->swapcache_low_wmark != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SWAPCACHE_LOW_WMARK, ++ param->swapcache_low_wmark), -1); ++ } + fclose(file); + } + +@@ -83,12 +95,15 @@ void init_proj_param(struct proj_test_param *param) + param->sleep = "1"; + param->interval = "1"; + param->loop = "1"; ++ param->sysmem_threshold = NULL; ++ param->swapcache_high_wmark = NULL; ++ param->swapcache_low_wmark = NULL; + param->file_name = TMP_PROJ_CONFIG; + param->proj_name = DEFAULT_PROJ; + param->expt = OPT_SUCCESS; + } + +-void do_add_proj_test(struct proj_test_param * param) ++void do_add_proj_test(struct proj_test_param *param) + { + GKeyFile *config = NULL; + +@@ -155,16 +170,16 @@ void construct_task_file(struct task_test_param *param) + CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_NAME, param->name), -1); + } + if (param->proj != NULL) { +- CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_PROJ, param->name), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_PROJ, param->proj), -1); + } + if (param->eng != NULL) { +- CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_ENG, param->name), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_ENG, param->eng), -1); + } + if (param->type != NULL) { +- CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_TYPE, param->name), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_TYPE, param->type), -1); + } + if (param->value != NULL) { +- CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_VALUE, param->name), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_VALUE, param->value), -1); + } + fclose(file); + } +@@ -174,6 +189,8 @@ void init_slide_task(struct slide_task_test_param *param) + init_task_param(¶m->task_param, "slide"); + param->max_threads = "1"; + param->T = "1"; ++ param->swap_flag = NULL; ++ param->swap_threshold = NULL; + } + + void add_slide_task(struct slide_task_test_param *param) +@@ -189,6 +206,12 @@ void add_slide_task(struct slide_task_test_param *param) + if (param->T != NULL) { + CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_T, param->T), -1); + } ++ if (param->swap_flag != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SWAP_FLAG, param->swap_flag), -1); ++ } ++ if (param->swap_threshold != NULL) { ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_SWAP_THRESHOLD, param->swap_threshold), -1); ++ } + fclose(file); + } + +diff --git a/etmem/test/common/test_common.h b/etmem/test/common/test_common.h +index 009c458..1ba20c7 100644 +--- a/etmem/test/common/test_common.h ++++ b/etmem/test/common/test_common.h +@@ -20,43 +20,51 @@ + + #include "etmemd_project.h" + +-#define CONFIG_NAME "name=%s\n" +-#define CONFIG_INTERVAL "interval=%s\n" +-#define CONFIG_LOOP "loop=%s\n" +-#define CONFIG_SLEEP "sleep=%s\n" +-#define TMP_PROJ_CONFIG "proj_tmp.config" +-#define DEFAULT_PROJ "default_proj" +- +-#define CONFIG_PROJ "project=%s\n" +-#define TMP_ENG_CONFIG "eng_tmp.config" +- +-#define CONFIG_ENG "engine=%s\n" +-#define CONFIG_TYPE "type=%s\n" +-#define CONFIG_VALUE "value=%s\n" +-#define TMP_TASK_CONFIG "task_tmp.config" +-#define DEFAULT_TASK "default_task" +- +-#define CONFIG_MAX_THREADS "max_threads=%s\n" +-#define CONFIG_T "T=%s\n" +- +-#define CONFIG_NODE_PAIR "node_pair=%s\n" +-#define CONFIG_THRESH "hot_threshold=%s\n" +-#define CONFIG_QUOTA "node_mig_quota=%s\n" +-#define CONFIG_RESV "node_hot_reserve=%s\n" +- +-#define CONFIG_VM_FLAGS "vm_flags=%s\n" +-#define CONFIG_ANON_ONLY "anon_only=%s\n" +-#define CONFIG_IGN_HOST "igno_host=%s\n" +- +-#define ONE_NODE_PAIR 2 +-#define TWO_NODE_PAIR 4 +-#define THREE_NODE_PAIR 5 ++#define CONFIG_NAME "name=%s\n" ++#define CONFIG_INTERVAL "interval=%s\n" ++#define CONFIG_LOOP "loop=%s\n" ++#define CONFIG_SLEEP "sleep=%s\n" ++#define CONFIG_SYSMEM_THRESHOLD "sysmem_threshold=%s\n" ++#define CONFIG_SWAPCACHE_HIGH_WMARK "swapcache_high_wmark=%s\n" ++#define CONFIG_SWAPCACHE_LOW_WMARK "swapcache_low_wmark=%s\n" ++#define TMP_PROJ_CONFIG "proj_tmp.config" ++#define DEFAULT_PROJ "default_proj" ++ ++#define CONFIG_PROJ "project=%s\n" ++#define TMP_ENG_CONFIG "eng_tmp.config" ++ ++#define CONFIG_ENG "engine=%s\n" ++#define CONFIG_TYPE "type=%s\n" ++#define CONFIG_VALUE "value=%s\n" ++#define TMP_TASK_CONFIG "task_tmp.config" ++#define DEFAULT_TASK "default_task" ++ ++#define CONFIG_MAX_THREADS "max_threads=%s\n" ++#define CONFIG_T "T=%s\n" ++#define CONFIG_SWAP_FLAG "swap_flag=%s\n" ++#define CONFIG_SWAP_THRESHOLD "swap_threshold=%s\n" ++ ++#define CONFIG_NODE_PAIR "node_pair=%s\n" ++#define CONFIG_THRESH "hot_threshold=%s\n" ++#define CONFIG_QUOTA "node_mig_quota=%s\n" ++#define CONFIG_RESV "node_hot_reserve=%s\n" ++ ++#define CONFIG_VM_FLAGS "vm_flags=%s\n" ++#define CONFIG_ANON_ONLY "anon_only=%s\n" ++#define CONFIG_IGN_HOST "ign_host=%s\n" ++ ++#define ONE_NODE_PAIR 2 ++#define TWO_NODE_PAIR 4 ++#define THREE_NODE_PAIR 6 + + + struct proj_test_param { + const char *sleep; + const char *interval; + const char *loop; ++ const char *sysmem_threshold; ++ const char *swapcache_high_wmark; ++ const char *swapcache_low_wmark; + const char *proj_name; + const char *file_name; + enum opt_result expt; +@@ -81,6 +89,8 @@ struct slide_task_test_param { + struct task_test_param task_param; + const char *max_threads; + const char *T; ++ const char *swap_flag; ++ const char *swap_threshold; + }; + + struct cslide_eng_test_param { +diff --git a/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt b/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt +new file mode 100644 +index 0000000..a9487af +--- /dev/null ++++ b/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt +@@ -0,0 +1,27 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-10 ++# * Description: CMakefileList for etmem_migrate_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_migrate_ops_llt) ++ ++add_executable(${EXE} etmem_migrate_ops_llt.c) ++ ++set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,get_mem_from_proc_file") ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c b/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c +new file mode 100644 +index 0000000..2758680 +--- /dev/null ++++ b/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c +@@ -0,0 +1,226 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-08-14 ++ * Description: This is a source file of the unit test for log functions in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include "etmemd.h" ++#include "etmemd_migrate.h" ++#include "etmemd_scan.h" ++#include "etmemd_project_exp.h" ++#include "etmemd_engine_exp.h" ++#include "etmemd_task_exp.h" ++#include "etmemd_task.h" ++ ++#include ++#include ++#include ++ ++#define WATER_LINE_TEMP 2 ++ ++/* Function replacement used for mock test. This function is used only in dt. */ ++int get_mem_from_proc_file(const char *pid, const char *file_name, ++ unsigned long *data, const char *cmpstr) ++{ ++ *data = 100; ++ return 0; ++} ++ ++void init_task_pid_param(struct task_pid *param) ++{ ++ param->pid = 1; ++ param->rt_swapin_rate = 0.0; ++ param->params = NULL; ++ param->next = NULL; ++} ++ ++static struct memory_grade *get_memory_grade(void) ++{ ++ struct memory_grade *memory_grade = NULL; ++ struct vmas *vmas = NULL; ++ struct page_refs *page_refs = NULL; ++ const char *pid = "1"; ++ ++ init_g_page_size(); ++ vmas = get_vmas(pid); ++ CU_ASSERT_PTR_NOT_NULL(vmas); ++ CU_ASSERT_EQUAL(get_page_refs(vmas, pid, &page_refs, NULL, NULL), 0); ++ free(vmas); ++ vmas = NULL; ++ ++ memory_grade = (struct memory_grade *)calloc(1, sizeof(struct memory_grade)); ++ CU_ASSERT_PTR_NOT_NULL(memory_grade); ++ ++ while (page_refs != NULL) ++ { ++ if ((page_refs)->count >= WATER_LINE_TEMP) { ++ page_refs = add_page_refs_into_memory_grade(page_refs, &memory_grade->hot_pages); ++ continue; ++ } ++ page_refs = add_page_refs_into_memory_grade(page_refs, &memory_grade->cold_pages); ++ } ++ ++ return memory_grade; ++} ++ ++static void test_etmem_migrate_error(void) ++{ ++ struct memory_grade *memory_grade = NULL; ++ ++ memory_grade = (struct memory_grade *)calloc(1, sizeof(struct memory_grade)); ++ CU_ASSERT_PTR_NOT_NULL(memory_grade); ++ ++ CU_ASSERT_EQUAL(etmemd_grade_migrate("", memory_grade), 0); ++ CU_ASSERT_EQUAL(etmemd_grade_migrate("no123", memory_grade), 0); ++ ++ free(memory_grade); ++ ++ memory_grade = get_memory_grade(); ++ CU_ASSERT_PTR_NOT_NULL(memory_grade); ++ CU_ASSERT_EQUAL(etmemd_grade_migrate("", memory_grade), -1); ++ CU_ASSERT_EQUAL(etmemd_grade_migrate("no123", memory_grade), -1); ++ ++ clean_memory_grade_unexpected(&memory_grade); ++ CU_ASSERT_PTR_NULL(memory_grade); ++} ++ ++static void test_etmem_migrate_ok(void) ++{ ++ struct memory_grade *memory_grade = NULL; ++ ++ memory_grade = get_memory_grade(); ++ CU_ASSERT_PTR_NOT_NULL(memory_grade); ++ CU_ASSERT_EQUAL(etmemd_grade_migrate("1", memory_grade), -1); ++ ++ clean_memory_grade_unexpected(&memory_grade); ++ CU_ASSERT_PTR_NULL(memory_grade); ++} ++ ++static void test_etmemd_reclaim_swapcache_error(void) ++{ ++ struct project proj = {0}; ++ struct engine eng = {0}; ++ struct task tk = {0}; ++ struct task_pid tk_pid = {0}; ++ ++ proj.swapcache_high_wmark = 5; ++ proj.swapcache_low_wmark = 3; ++ tk_pid.tk = &tk; ++ tk.eng = ŋ ++ eng.proj = &proj; ++ ++ CU_ASSERT_EQUAL(etmemd_reclaim_swapcache(NULL), -1); ++ ++ init_task_pid_param(&tk_pid); ++ tk_pid.pid = 0; ++ proj.wmark_set = false; ++ CU_ASSERT_EQUAL(etmemd_reclaim_swapcache(&tk_pid), -1); ++ ++ tk_pid.pid = 0; ++ proj.wmark_set = true; ++ CU_ASSERT_EQUAL(etmemd_reclaim_swapcache(&tk_pid), -1); ++} ++ ++static void test_etmemd_reclaim_swapcache_ok(void) ++{ ++ struct project proj = {0}; ++ struct engine eng = {0}; ++ struct task tk = {0}; ++ struct task_pid tk_pid = {0}; ++ ++ tk_pid.tk = &tk; ++ tk.eng = ŋ ++ eng.proj = &proj; ++ ++ init_task_pid_param(&tk_pid); ++ proj.swapcache_high_wmark = -1; ++ proj.swapcache_low_wmark = -1; ++ CU_ASSERT_EQUAL(etmemd_reclaim_swapcache(&tk_pid), 0); ++ ++ proj.swapcache_high_wmark = 100; ++ proj.swapcache_low_wmark = 3; ++ CU_ASSERT_EQUAL(etmemd_reclaim_swapcache(&tk_pid), 0); ++ ++ init_task_pid_param(&tk_pid); ++ proj.swapcache_high_wmark = 5; ++ proj.swapcache_low_wmark = 3; ++ proj.wmark_set = false; ++ CU_ASSERT_EQUAL(etmemd_reclaim_swapcache(&tk_pid), 0); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_migrate_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_etmem_migrate_error) == NULL || ++ CU_ADD_TEST(suite, test_etmem_migrate_ok) == NULL || ++ CU_ADD_TEST(suite, test_etmemd_reclaim_swapcache_error) == NULL || ++ CU_ADD_TEST(suite, test_etmemd_reclaim_swapcache_ok) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_migrate.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c b/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c +index a01e8e8..65c1fc6 100644 +--- a/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c ++++ b/etmem/test/etmem_project_ops_llt_test/etmem_project_ops_llt.c +@@ -117,6 +117,161 @@ static void etmem_pro_add_interval(void) + destroy_proj_config(config); + } + ++static void etmem_pro_add_sysmem_threshold_error(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.sysmem_threshold = "101"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "abc"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "a10b"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "10a"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "-1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_sysmem_threshold_ok(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.sysmem_threshold = "0"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "99"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.sysmem_threshold = "100"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_swapcache_mark_error(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.swapcache_high_wmark = "-1"; ++ param.swapcache_low_wmark = "-1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "1"; ++ param.swapcache_low_wmark = "-1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "-1"; ++ param.swapcache_low_wmark = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "1"; ++ param.swapcache_low_wmark = "2"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "101"; ++ param.swapcache_low_wmark = "100"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "100"; ++ param.swapcache_low_wmark = "101"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "101"; ++ param.swapcache_low_wmark = "101"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "5"; ++ param.swapcache_low_wmark = NULL; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = NULL; ++ param.swapcache_low_wmark = "5"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_INVAL); ++ destroy_proj_config(config); ++} ++ ++static void etmem_pro_add_swapcache_mark_ok(void) ++{ ++ struct proj_test_param param; ++ GKeyFile *config = NULL; ++ ++ init_proj_param(¶m); ++ ++ param.swapcache_high_wmark = "2"; ++ param.swapcache_low_wmark = "1"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++ ++ param.swapcache_high_wmark = "100"; ++ param.swapcache_low_wmark = "99"; ++ config = construct_proj_config(¶m); ++ CU_ASSERT_EQUAL(etmemd_project_add(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), OPT_SUCCESS); ++ destroy_proj_config(config); ++} ++ + static void etmem_pro_add_loop(void) + { + struct proj_test_param param; +@@ -231,6 +386,8 @@ void test_etmem_prj_add_error(void) + etmem_pro_add_loop(); + etmem_pro_add_sleep(); + etmem_pro_lack_loop(); ++ etmem_pro_add_sysmem_threshold_error(); ++ etmem_pro_add_swapcache_mark_error(); + } + + void test_etmem_prj_del_error(void) +@@ -256,6 +413,8 @@ static void add_project_once(void) + struct proj_test_param param; + GKeyFile *config = NULL; + ++ etmem_pro_add_sysmem_threshold_ok(); ++ etmem_pro_add_swapcache_mark_ok(); + init_proj_param(¶m); + + CU_ASSERT_EQUAL(etmemd_project_show(NULL, 0), OPT_PRO_NOEXIST); +@@ -348,7 +507,7 @@ void test_etmem_mig_stop_error(void) + CU_ASSERT_EQUAL(etmemd_migrate_stop(""), OPT_PRO_NOEXIST); + CU_ASSERT_EQUAL(etmemd_migrate_stop("ETMEM"), OPT_PRO_NOEXIST); + CU_ASSERT_EQUAL(etmemd_migrate_stop("ET^$%*MEM"), OPT_PRO_NOEXIST); +- ++ + param.proj_name = "add_for_migrate_stop_test"; + do_add_proj_test(¶m); + +diff --git a/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c b/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c +index 0cd2ecc..84fcf69 100644 +--- a/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c ++++ b/etmem/test/etmem_scan_ops_llt_test/etmem_scan_ops_llt.c +@@ -243,7 +243,7 @@ static void test_get_page_refs_valid() + + unsigned long use_rss; + +- CU_ASSERT_EQUAL(get_page_refs(vmas, pid, &page_refs, &use_rss, 0), 0); ++ CU_ASSERT_EQUAL(get_page_refs(vmas, pid, &page_refs, &use_rss, NULL), 0); + CU_ASSERT_PTR_NOT_NULL(page_refs); + CU_ASSERT_NOT_EQUAL(use_rss, 0); + +@@ -309,7 +309,7 @@ static void test_add_pg_to_mem_grade() + CU_ASSERT_EQUAL(etmemd_scan_init(), 0); + + vma = get_vmas(pid); +- CU_ASSERT_EQUAL(get_page_refs(vma, pid, &page_refs, NULL, 0), 0); ++ CU_ASSERT_EQUAL(get_page_refs(vma, pid, &page_refs, NULL, NULL), 0); + page_refs = add_page_refs_into_memory_grade(page_refs, &list); + CU_ASSERT_PTR_NOT_NULL(page_refs); + CU_ASSERT_PTR_NOT_NULL(list); +-- +1.8.3.1 + diff --git a/0066-etmem-add-sysmem_threshold-and-swap_threshold-parame.patch b/0066-etmem-add-sysmem_threshold-and-swap_threshold-parame.patch new file mode 100644 index 0000000000000000000000000000000000000000..5374d07b4d4cbfd016acc16aae4ea8b944ecb44a --- /dev/null +++ b/0066-etmem-add-sysmem_threshold-and-swap_threshold-parame.patch @@ -0,0 +1,415 @@ +From 9707219f4ec2b12012620a3e5cec90b61a3ca2c4 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Tue, 18 Jan 2022 11:03:13 +0800 +Subject: [PATCH 16/33] etmem: add sysmem_threshold and swap_threshold + parameters to etmem + +As a memory expansion tool, etmem performs memory swap operation +for the target process by default after it is enabled. However, +in some specific scenarios, in order to obtain the ultimate +performance of the business, it is necessary to consider +the timing of memory swapping by etmem. + +Add the sysmem_threshold parameter to control the start and +stop of memory swap out when the system available memory +meets the requirements. + +Add the swap_threshold parameter to limit the absolute +value of the memory size reserved by the process in DRAM. +When the target process memory is lower than this value, do not +swap out any memory. + +Signed-off-by: liubo +--- + etmem/conf/slide_conf.yaml | 2 + + etmem/inc/etmemd_inc/etmemd_common.h | 10 +++ + etmem/inc/etmemd_inc/etmemd_project_exp.h | 1 + + etmem/inc/etmemd_inc/etmemd_slide.h | 1 + + etmem/src/etmemd_src/etmemd_common.c | 58 +++++++++++++- + etmem/src/etmemd_src/etmemd_project.c | 32 ++++++-- + etmem/src/etmemd_src/etmemd_slide.c | 123 ++++++++++++++++++++++++++++++ + 7 files changed, 220 insertions(+), 7 deletions(-) + +diff --git a/etmem/conf/slide_conf.yaml b/etmem/conf/slide_conf.yaml +index 75f0220..511d657 100644 +--- a/etmem/conf/slide_conf.yaml ++++ b/etmem/conf/slide_conf.yaml +@@ -4,6 +4,7 @@ scan_type=page + loop=1 + interval=1 + sleep=1 ++sysmem_threshold=50 + + [engine] + name=slide +@@ -17,3 +18,4 @@ type=name + value=mysql + T=1 + max_threads=1 ++swap_threshold=10g +diff --git a/etmem/inc/etmemd_inc/etmemd_common.h b/etmem/inc/etmemd_inc/etmemd_common.h +index 8d18f8a..576d38a 100644 +--- a/etmem/inc/etmemd_inc/etmemd_common.h ++++ b/etmem/inc/etmemd_inc/etmemd_common.h +@@ -21,6 +21,7 @@ + + #define PROC_PATH "/proc/" + #define STATUS_FILE "/status" ++#define PROC_MEMINFO "meminfo" + #define SWAPIN "SwapIN" + #define VMRSS "VmRSS" + #define VMSWAP "VmSwap" +@@ -30,14 +31,21 @@ + #define ETMEMD_MAX_PARAMETER_NUM 6 + #define BYTE_TO_KB(s) ((s) >> 10) + #define KB_TO_BYTE(s) ((s) << 10) ++#define CONVERT_GB_2_KB (1024 * 1024) + + #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + + /* in some system the max length of pid may be larger than 5, so we use 10 herr */ + #define PID_STR_MAX_LEN 10 ++#define SWAP_THRESHOLD_MAX_LEN 10 + + #define PIPE_FD_LEN 2 + ++enum swap_type { ++ DONT_SWAP = 0, ++ DO_SWAP, ++}; ++ + /* + * function: parse cmdline passed to etmemd server. + * +@@ -65,4 +73,6 @@ int get_mem_from_proc_file(const char *pid, const char *file_name, unsigned long + + int dprintf_all(int fd, const char *format, ...); + ++int get_swap_threshold_inKB(char *string); ++ + #endif +diff --git a/etmem/inc/etmemd_inc/etmemd_project_exp.h b/etmem/inc/etmemd_inc/etmemd_project_exp.h +index 8740f7e..fc3c85e 100644 +--- a/etmem/inc/etmemd_inc/etmemd_project_exp.h ++++ b/etmem/inc/etmemd_inc/etmemd_project_exp.h +@@ -42,6 +42,7 @@ struct project { + char *name; + enum scan_type type; + void *scan_param; ++ int sysmem_threshold; + bool start; + struct engine *engs; + +diff --git a/etmem/inc/etmemd_inc/etmemd_slide.h b/etmem/inc/etmemd_inc/etmemd_slide.h +index 93de502..7c80502 100644 +--- a/etmem/inc/etmemd_inc/etmemd_slide.h ++++ b/etmem/inc/etmemd_inc/etmemd_slide.h +@@ -22,6 +22,7 @@ + struct slide_params { + struct task_executor *executor; + int t; /* watermark */ ++ int swap_threshold; + uint8_t dram_percent; + }; + +diff --git a/etmem/src/etmemd_src/etmemd_common.c b/etmem/src/etmemd_src/etmemd_common.c +index ebf6232..caa5826 100644 +--- a/etmem/src/etmemd_src/etmemd_common.c ++++ b/etmem/src/etmemd_src/etmemd_common.c +@@ -256,7 +256,7 @@ static char *etmemd_get_proc_file_str(const char *pid, const char *file) + char *file_name = NULL; + size_t file_str_size; + +- file_str_size = strlen(PROC_PATH) + strlen(pid) + strlen(file) + 1; ++ file_str_size = strlen(PROC_PATH) + strlen(file) + 1 + (pid == NULL ? 0 : strlen(pid)); + file_name = (char *)calloc(file_str_size, sizeof(char)); + if (file_name == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "malloc for %s path fail\n", file); +@@ -264,7 +264,7 @@ static char *etmemd_get_proc_file_str(const char *pid, const char *file) + } + + if (snprintf_s(file_name, file_str_size, file_str_size - 1, +- "%s%s%s", PROC_PATH, pid, file) == -1) { ++ "%s%s%s", PROC_PATH, pid ? pid : "", file) == -1) { + etmemd_log(ETMEMD_LOG_ERR, "snprintf for %s fail\n", file); + free(file_name); + return NULL; +@@ -495,3 +495,57 @@ unsigned long get_pagesize(void) + + return (unsigned long)pagesize; + } ++ ++int get_swap_threshold_inKB(char *string) ++{ ++ int len; ++ int i; ++ int ret = -1; ++ char *swap_threshold_string = NULL; ++ int swap_threshold_inGB; ++ int swap_threshold_inKB; ++ ++ if (string == NULL) { ++ goto out; ++ } ++ ++ len = strlen(string); ++ if (len > SWAP_THRESHOLD_MAX_LEN) { ++ etmemd_log(ETMEMD_LOG_ERR, "swap_threshold string is too long.\n"); ++ goto out; ++ } ++ ++ swap_threshold_string = (char *)calloc(len, sizeof(char)); ++ if (swap_threshold_string == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "calloc swap_threshold_string fail.\n"); ++ goto out; ++ } ++ ++ for (i = 0; i < len - 1; i++) { ++ if (isdigit(string[i])) { ++ swap_threshold_string[i] = string[i]; ++ continue; ++ } ++ etmemd_log(ETMEMD_LOG_ERR, "the swap_threshold contain wrong parameter.\n"); ++ goto free_out; ++ } ++ ++ if (string[i] != 'g' && string[i] != 'G') { ++ etmemd_log(ETMEMD_LOG_ERR, "the swap_threshold should in G or g.\n"); ++ goto free_out; ++ } ++ ++ if (get_int_value(swap_threshold_string, &swap_threshold_inGB) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get_int_value swap_threshold faild.\n"); ++ goto free_out; ++ } ++ ++ swap_threshold_inKB = swap_threshold_inGB * CONVERT_GB_2_KB; ++ ret = swap_threshold_inKB; ++ ++free_out: ++ free(swap_threshold_string); ++ ++out: ++ return ret; ++} +diff --git a/etmem/src/etmemd_src/etmemd_project.c b/etmem/src/etmemd_src/etmemd_project.c +index fa4293b..459e140 100644 +--- a/etmem/src/etmemd_src/etmemd_project.c ++++ b/etmem/src/etmemd_src/etmemd_project.c +@@ -30,12 +30,13 @@ + #include "etmemd_file.h" + #include "etmemd_log.h" + +-#define MAX_INTERVAL_VALUE 1200 +-#define MAX_SLEEP_VALUE 1200 +-#define MAX_LOOP_VALUE 120 ++#define MAX_INTERVAL_VALUE 1200 ++#define MAX_SLEEP_VALUE 1200 ++#define MAX_LOOP_VALUE 120 ++#define MAX_SYSMEM_THRESHOLD_VALUE 100 + +-#define MAX_OBJ_NAME_LEN 64 +-#define MIN_NR_MIN_VAL 3 ++#define MAX_OBJ_NAME_LEN 64 ++#define MIN_NR_MIN_VAL 3 + + static SLIST_HEAD(project_list, project) g_projects = SLIST_HEAD_INITIALIZER(g_projects); + +@@ -630,9 +631,27 @@ static int fill_project_scan_type(void *obj, void *val) + return 0; + } + ++/* fill the project parameter: sysmem_threshold ++ * sysmem_threshold: [0, 100]. do not swap any memory out if system free memory is higher than sysmem_threshold */ ++static int fill_project_sysmem_threshold(void *obj, void *val) ++{ ++ struct project *proj = (struct project *)obj; ++ int sysmem_threshold = parse_to_int(val); ++ ++ if (sysmem_threshold < 0 || sysmem_threshold > MAX_SYSMEM_THRESHOLD_VALUE) { ++ etmemd_log(ETMEMD_LOG_WARN, "invaild project sysmem_threshold value %d, it must between 0 and 100.\n", ++ sysmem_threshold, MAX_SYSMEM_THRESHOLD_VALUE); ++ sysmem_threshold = -1; ++ } ++ ++ proj->sysmem_threshold = sysmem_threshold; ++ return 0; ++} ++ + static struct config_item g_project_config_items[] = { + {"name", STR_VAL, fill_project_name, false}, + {"scan_type", STR_VAL, fill_project_scan_type, false}, ++ {"sysmem_threshold", INT_VAL, fill_project_sysmem_threshold, true}, + }; + + static void clear_project(struct project *proj) +@@ -688,6 +707,9 @@ enum opt_result etmemd_project_add(GKeyFile *config) + etmemd_log(ETMEMD_LOG_ERR, "alloc memory for project fail\n"); + return OPT_INTER_ERR; + } ++ ++ proj->sysmem_threshold = -1; ++ + if (project_fill_by_conf(config, proj) != 0) { + etmemd_log(ETMEMD_LOG_ERR, "fill project from configuration file fail\n"); + free(proj); +diff --git a/etmem/src/etmemd_src/etmemd_slide.c b/etmem/src/etmemd_src/etmemd_slide.c +index 8362224..cbc4b17 100644 +--- a/etmem/src/etmemd_src/etmemd_slide.c ++++ b/etmem/src/etmemd_src/etmemd_slide.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include "securec.h" + #include "etmemd_log.h" +@@ -106,6 +107,104 @@ static int slide_do_migrate(unsigned int pid, const struct memory_grade *memory_ + return ret; + } + ++static int check_sysmem_lower_threshold(struct task_pid *tk_pid) ++{ ++ unsigned long mem_total; ++ unsigned long mem_free; ++ int vm_cmp; ++ int ret; ++ ++ ret = get_mem_from_proc_file(NULL, PROC_MEMINFO, &mem_total, "MemTotal"); ++ if (ret != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get memtotal fail\n"); ++ return DONT_SWAP; ++ } ++ ++ ret = get_mem_from_proc_file(NULL, PROC_MEMINFO, &mem_free, "MemFree"); ++ if (ret != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get memfree fail\n"); ++ return DONT_SWAP; ++ } ++ ++ /* Calculate the free memory percentage in 0 - 100 */ ++ vm_cmp = (mem_free * 100) / mem_total; ++ if (vm_cmp < tk_pid->tk->eng->proj->sysmem_threshold) { ++ return DO_SWAP; ++ } ++ ++ return DONT_SWAP; ++} ++ ++static int check_pid_should_swap(const char *pid, unsigned long vmrss, const struct task_pid *tk_pid) ++{ ++ unsigned long vmswap; ++ unsigned long vmcmp; ++ int ret; ++ ++ ret = get_mem_from_proc_file(pid, STATUS_FILE, &vmswap, "VmSwap"); ++ if (ret != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get VmSwap fail\n"); ++ return DONT_SWAP; ++ } ++ ++ /* Calculate the total amount of memory that can be swappout for the current process ++ * and check whether the memory is larger than the current swapout amount. ++ * If true, continue swap-out; otherwise, abort the swap-out process. */ ++ vmcmp = (vmrss + vmswap) / 100 * tk_pid->tk->eng->proj->sysmem_threshold; ++ if (vmcmp > vmswap) { ++ return DO_SWAP; ++ } ++ ++ return DONT_SWAP; ++} ++ ++static int check_pidmem_lower_threshold(struct task_pid *tk_pid) ++{ ++ struct slide_params *params = NULL; ++ unsigned long vmrss; ++ int ret; ++ char pid_str[PID_STR_MAX_LEN] = {0}; ++ ++ params = (struct slide_params *)tk_pid->tk->params; ++ if (params == NULL) { ++ return DONT_SWAP; ++ } ++ ++ if (snprintf_s(pid_str, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%u", tk_pid->pid) <= 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "snprintf pid fail %u", tk_pid->pid); ++ return DONT_SWAP; ++ } ++ ++ ret = get_mem_from_proc_file(pid_str, STATUS_FILE, &vmrss, "VmRSS"); ++ if (ret != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get VmRSS fail\n"); ++ return DONT_SWAP; ++ } ++ ++ if (params->swap_threshold == 0) { ++ return check_pid_should_swap(pid_str, vmrss, tk_pid); ++ } ++ ++ if ((int)vmrss > params->swap_threshold) { ++ return DO_SWAP; ++ } ++ ++ return DONT_SWAP; ++} ++ ++static int check_should_swap(struct task_pid *tk_pid) ++{ ++ if (tk_pid->tk->eng->proj->sysmem_threshold == -1) { ++ return DO_SWAP; ++ } ++ ++ if (check_sysmem_lower_threshold(tk_pid) == DONT_SWAP) { ++ return DONT_SWAP; ++ } ++ ++ return check_pidmem_lower_threshold(tk_pid); ++} ++ + static void *slide_executor(void *arg) + { + struct task_pid *tk_pid = (struct task_pid *)arg; +@@ -113,6 +212,10 @@ static void *slide_executor(void *arg) + struct memory_grade *memory_grade = NULL; + struct page_sort *page_sort = NULL; + ++ if (check_should_swap(tk_pid) == DONT_SWAP) { ++ return NULL; ++ } ++ + /* register cleanup function in case of unexpected cancellation detected, + * and register for memory_grade first, because it needs to clean after page_refs is cleaned */ + pthread_cleanup_push(clean_memory_grade_unexpected, &memory_grade); +@@ -194,8 +297,28 @@ static int fill_task_dram_percent(void *obj, void *val) + return 0; + } + ++static int fill_task_swap_threshold(void *obj, void *val) ++{ ++ struct slide_params *params = (struct slide_params *)obj; ++ char *swap_threshold_string = (char *)val; ++ int swap_threshold = get_swap_threshold_inKB(swap_threshold_string); ++ ++ free(swap_threshold_string); ++ ++ if (swap_threshold < 0) { ++ etmemd_log(ETMEMD_LOG_WARN, ++ "parse swap_threshold failed.\n"); ++ return -1; ++ } ++ ++ params->swap_threshold = swap_threshold; ++ ++ return 0; ++} ++ + static struct config_item g_slide_task_config_items[] = { + {"T", INT_VAL, fill_task_threshold, false}, ++ {"swap_threshold", STR_VAL, fill_task_swap_threshold, true}, + {"dram_percent", INT_VAL, fill_task_dram_percent, true}, + }; + +-- +1.8.3.1 + diff --git a/0067-etmem-add-swapcache-reclaim-to-etmem.patch b/0067-etmem-add-swapcache-reclaim-to-etmem.patch new file mode 100644 index 0000000000000000000000000000000000000000..515a8f58b9bbffcc5b7990e583c36904391ce40e --- /dev/null +++ b/0067-etmem-add-swapcache-reclaim-to-etmem.patch @@ -0,0 +1,552 @@ +From 8a7c297694bfad83bdc826aea3c0fea84098a4fb Mon Sep 17 00:00:00 2001 +From: liubo +Date: Tue, 18 Jan 2022 15:21:13 +0800 +Subject: [PATCH 17/33] etmem: add swapcache reclaim to etmem + +When etmem performs the memory swap operation, it will +occupy part of the swapcache memory. To further save +memory, the swapcache memory recovery function is +added, which depends on etmem_swap.ko + +Add swapcache_high_wmark and swapcache_low_wmark field +to set the available watermark of swapcache memory. +When the swapcache memory usage is higher than high_wmark, +the swapcache memory recovery is triggered until it is less +than low wmark. + +Signed-off-by: liubo +--- + etmem/conf/slide_conf.yaml | 2 + + etmem/inc/etmemd_inc/etmemd_common.h | 50 ++++++++----- + etmem/inc/etmemd_inc/etmemd_migrate.h | 1 + + etmem/inc/etmemd_inc/etmemd_project_exp.h | 3 + + etmem/src/etmemd_src/etmemd_common.c | 48 +++++++------ + etmem/src/etmemd_src/etmemd_cslide.c | 12 +++- + etmem/src/etmemd_src/etmemd_migrate.c | 113 +++++++++++++++++++++++++++++- + etmem/src/etmemd_src/etmemd_project.c | 56 ++++++++++++++- + etmem/src/etmemd_src/etmemd_scan.c | 14 +++- + etmem/src/etmemd_src/etmemd_slide.c | 4 ++ + 10 files changed, 255 insertions(+), 48 deletions(-) + +diff --git a/etmem/conf/slide_conf.yaml b/etmem/conf/slide_conf.yaml +index 511d657..f55c508 100644 +--- a/etmem/conf/slide_conf.yaml ++++ b/etmem/conf/slide_conf.yaml +@@ -5,6 +5,8 @@ loop=1 + interval=1 + sleep=1 + sysmem_threshold=50 ++swapcache_high_wmark=10 ++swapcache_low_wmark=6 + + [engine] + name=slide +diff --git a/etmem/inc/etmemd_inc/etmemd_common.h b/etmem/inc/etmemd_inc/etmemd_common.h +index 576d38a..ced606e 100644 +--- a/etmem/inc/etmemd_inc/etmemd_common.h ++++ b/etmem/inc/etmemd_inc/etmemd_common.h +@@ -18,34 +18,47 @@ + + #include + #include ++#include + +-#define PROC_PATH "/proc/" +-#define STATUS_FILE "/status" +-#define PROC_MEMINFO "meminfo" +-#define SWAPIN "SwapIN" +-#define VMRSS "VmRSS" +-#define VMSWAP "VmSwap" +-#define FILE_LINE_MAX_LEN 1024 +-#define KEY_VALUE_MAX_LEN 64 +-#define DECIMAL_RADIX 10 +-#define ETMEMD_MAX_PARAMETER_NUM 6 +-#define BYTE_TO_KB(s) ((s) >> 10) +-#define KB_TO_BYTE(s) ((s) << 10) +-#define CONVERT_GB_2_KB (1024 * 1024) +- +-#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) ++#define PROC_PATH "/proc/" ++#define STATUS_FILE "/status" ++#define PROC_MEMINFO "meminfo" ++#define SWAPIN "SwapIN" ++#define VMRSS "VmRSS" ++#define VMSWAP "VmSwap" ++ ++#define FILE_LINE_MAX_LEN 1024 ++#define KEY_VALUE_MAX_LEN 64 ++#define DECIMAL_RADIX 10 ++#define ETMEMD_MAX_PARAMETER_NUM 6 ++ ++#define BYTE_TO_KB(s) ((s) >> 10) ++#define KB_TO_BYTE(s) ((s) << 10) ++#define CONVERT_GB_2_KB (1024 * 1024) ++ ++#define MAX_SWAPCACHE_WMARK_VALUE 100 ++ ++#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + + /* in some system the max length of pid may be larger than 5, so we use 10 herr */ +-#define PID_STR_MAX_LEN 10 ++#define PID_STR_MAX_LEN 10 + #define SWAP_THRESHOLD_MAX_LEN 10 + +-#define PIPE_FD_LEN 2 ++#define PIPE_FD_LEN 2 ++ ++#define IDLE_SCAN_MAGIC 0x66 ++#define IDLE_SCAN_ADD_FLAGS _IOW(IDLE_SCAN_MAGIC, 0x0, unsigned int) + + enum swap_type { + DONT_SWAP = 0, + DO_SWAP, + }; + ++struct ioctl_para { ++ unsigned long ioctl_cmd; ++ int ioctl_parameter; ++}; ++ + /* + * function: parse cmdline passed to etmemd server. + * +@@ -65,7 +78,8 @@ int get_unsigned_int_value(const char *val, unsigned int *value); + int get_unsigned_long_value(const char *val, unsigned long *value); + void etmemd_safe_free(void **ptr); + +-FILE *etmemd_get_proc_file(const char *pid, const char *file, int flags, const char *mode); ++FILE *etmemd_get_proc_file(const char *pid, const char *file, const char *mode); ++int etmemd_send_ioctl_cmd(FILE *fp, struct ioctl_para *request); + + int get_keyword_and_value(const char *str, char *key, char *val); + unsigned long get_pagesize(void); +diff --git a/etmem/inc/etmemd_inc/etmemd_migrate.h b/etmem/inc/etmemd_inc/etmemd_migrate.h +index ef20bde..f8eb621 100644 +--- a/etmem/inc/etmemd_inc/etmemd_migrate.h ++++ b/etmem/inc/etmemd_inc/etmemd_migrate.h +@@ -27,5 +27,6 @@ + #define SWAP_ADDR_LEN 20 + + int etmemd_grade_migrate(const char* pid, const struct memory_grade *memory_grade); ++int etmemd_reclaim_swapcache(const struct task_pid *tk_pid); + unsigned long check_should_migrate(const struct task_pid *tk_pid); + #endif +diff --git a/etmem/inc/etmemd_inc/etmemd_project_exp.h b/etmem/inc/etmemd_inc/etmemd_project_exp.h +index fc3c85e..2fe8d90 100644 +--- a/etmem/inc/etmemd_inc/etmemd_project_exp.h ++++ b/etmem/inc/etmemd_inc/etmemd_project_exp.h +@@ -43,7 +43,10 @@ struct project { + enum scan_type type; + void *scan_param; + int sysmem_threshold; ++ int swapcache_high_wmark; ++ int swapcache_low_wmark; + bool start; ++ bool wmark_set; + struct engine *engs; + + SLIST_ENTRY(project) entry; +diff --git a/etmem/src/etmemd_src/etmemd_common.c b/etmem/src/etmemd_src/etmemd_common.c +index caa5826..bb72fd0 100644 +--- a/etmem/src/etmemd_src/etmemd_common.c ++++ b/etmem/src/etmemd_src/etmemd_common.c +@@ -32,9 +32,6 @@ + #include "etmemd_rpc.h" + #include "etmemd_log.h" + +-#define IDLE_SCAN_MAGIC 0x66 +-#define IDLE_SCAN_ADD_FLAGS _IOW(IDLE_SCAN_MAGIC, 0x0, unsigned int) +- + static void usage(void) + { + printf("\nusage of etmemd:\n" +@@ -273,10 +270,32 @@ static char *etmemd_get_proc_file_str(const char *pid, const char *file) + return file_name; + } + +-FILE *etmemd_get_proc_file(const char *pid, const char *file, int flags, const char *mode) ++int etmemd_send_ioctl_cmd(FILE *fp, struct ioctl_para *request) + { +- char *file_name = NULL; + int fd = -1; ++ ++ if (fp == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "send ioctl cmd fail, fp is null\n"); ++ return -1; ++ } ++ ++ fd = fileno(fp); ++ if (fd < 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "send ioctl cmd fail, get fd fail\n"); ++ return -1; ++ } ++ ++ if (request == NULL || ioctl(fd, request->ioctl_cmd, &request->ioctl_parameter) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "send ioctl cmd fail, request is wrong\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++FILE *etmemd_get_proc_file(const char *pid, const char *file, const char *mode) ++{ ++ char *file_name = NULL; + FILE *fp = NULL; + + file_name = etmemd_get_proc_file_str(pid, file); +@@ -287,25 +306,8 @@ FILE *etmemd_get_proc_file(const char *pid, const char *file, int flags, const c + fp = fopen(file_name, mode); + if (fp == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "open file %s fail\n", file_name); +- goto free_file_name; +- } +- +- fd = fileno(fp); +- if (fd < 0) { +- etmemd_log(ETMEMD_LOG_ERR, "get fd of file %s fail\n", file_name); +- fclose(fp); +- fp = NULL; +- goto free_file_name; +- } +- +- if (flags != 0 && ioctl(fd, IDLE_SCAN_ADD_FLAGS, &flags) != 0) { +- etmemd_log(ETMEMD_LOG_ERR, "set idle flags for %s fail with %s\n", pid, strerror(errno)); +- fclose(fp); +- fp = NULL; +- goto free_file_name; + } + +-free_file_name: + free(file_name); + return fp; + } +@@ -453,7 +455,7 @@ int get_mem_from_proc_file(const char *pid, const char *file_name, unsigned long + unsigned long val; + int ret = -1; + +- file = etmemd_get_proc_file(pid, file_name, 0, "r"); ++ file = etmemd_get_proc_file(pid, file_name, "r"); + if (file == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "cannot open %s for pid %s\n", file_name, pid); + return ret; +diff --git a/etmem/src/etmemd_src/etmemd_cslide.c b/etmem/src/etmemd_src/etmemd_cslide.c +index b3d1637..cbaa2e8 100644 +--- a/etmem/src/etmemd_src/etmemd_cslide.c ++++ b/etmem/src/etmemd_src/etmemd_cslide.c +@@ -1280,18 +1280,28 @@ static int cslide_scan_vmas(struct cslide_pid_params *params) + uint64_t i; + int fd; + struct cslide_task_params *task_params = params->task_params; ++ struct ioctl_para ioctl_para = { ++ .ioctl_cmd = IDLE_SCAN_ADD_FLAGS, ++ .ioctl_parameter = task_params->scan_flags, ++ }; + + if (snprintf_s(pid, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%u", params->pid) <= 0) { + etmemd_log(ETMEMD_LOG_ERR, "snpintf pid %u fail\n", params->pid); + return -1; + } + +- scan_fp = etmemd_get_proc_file(pid, IDLE_SCAN_FILE, task_params->scan_flags, "r"); ++ scan_fp = etmemd_get_proc_file(pid, IDLE_SCAN_FILE, "r"); + if (scan_fp == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "open %s file for pid %u fail\n", IDLE_SCAN_FILE, params->pid); + return -1; + } + ++ if (task_params->scan_flags != 0 && etmemd_send_ioctl_cmd(scan_fp, &ioctl_para) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "etmemd send_ioctl_cmd %s file for pid %u fail\n", IDLE_SCAN_FILE, params->pid); ++ fclose(scan_fp); ++ return -1; ++ } ++ + fd = fileno(scan_fp); + if (fd == -1) { + fclose(scan_fp); +diff --git a/etmem/src/etmemd_src/etmemd_migrate.c b/etmem/src/etmemd_src/etmemd_migrate.c +index 639d570..87bfde0 100644 +--- a/etmem/src/etmemd_src/etmemd_migrate.c ++++ b/etmem/src/etmemd_src/etmemd_migrate.c +@@ -15,14 +15,24 @@ + + #include + #include ++#include ++#include ++#include ++#include ++#include + + #include "securec.h" + #include "etmemd.h" + #include "etmemd_migrate.h" ++#include "etmemd_project.h" + #include "etmemd_common.h" + #include "etmemd_slide.h" + #include "etmemd_log.h" + ++#define RECLAIM_SWAPCACHE_MAGIC 0x77 ++#define RECLAIM_SWAPCACHE_ON _IOW(RECLAIM_SWAPCACHE_MAGIC, 0x1, unsigned int) ++#define SET_SWAPCACHE_WMARK _IOW(RECLAIM_SWAPCACHE_MAGIC, 0x2, unsigned int) ++ + static char *get_swap_string(struct page_refs **page_refs, int batchsize) + { + char *swap_str = NULL; +@@ -70,7 +80,7 @@ static int etmemd_migrate_mem(const char *pid, const char *grade_path, struct pa + return 0; + } + +- fp = etmemd_get_proc_file(pid, grade_path, 0, "r+"); ++ fp = etmemd_get_proc_file(pid, grade_path, "r+"); + if (fp == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "cannot open %s for pid %s\n", grade_path, pid); + return -1; +@@ -98,6 +108,107 @@ static int etmemd_migrate_mem(const char *pid, const char *grade_path, struct pa + return 0; + } + ++static bool check_should_reclaim_swapcache(const struct task_pid *tk_pid) ++{ ++ struct project *proj = tk_pid->tk->eng->proj; ++ unsigned long mem_total; ++ unsigned long swapcache_total; ++ int ret; ++ ++ if (proj->swapcache_high_wmark == 0) { ++ return false; ++ } ++ ++ ret = get_mem_from_proc_file(NULL, PROC_MEMINFO, &mem_total, "MemTotal"); ++ if (ret != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get memtotal fail\n"); ++ return false; ++ } ++ ++ ret = get_mem_from_proc_file(NULL, PROC_MEMINFO, &swapcache_total, "SwapCached"); ++ if (ret != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get swapcache_total fail\n"); ++ return false; ++ } ++ ++ if ((swapcache_total / proj->swapcache_high_wmark) <= (mem_total / MAX_SWAPCACHE_WMARK_VALUE)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static int set_swapcache_wmark(const struct task_pid *tk_pid, const char *pid_str) ++{ ++ int swapcache_wmark; ++ struct project *proj = tk_pid->tk->eng->proj; ++ FILE *fp = NULL; ++ struct ioctl_para ioctl_para = { ++ .ioctl_cmd = SET_SWAPCACHE_WMARK, ++ }; ++ ++ swapcache_wmark = (proj->swapcache_low_wmark & 0x00ff) | (proj->swapcache_high_wmark << 8 & 0xff00); ++ ioctl_para.ioctl_parameter = swapcache_wmark; ++ ++ fp = etmemd_get_proc_file(pid_str, COLD_PAGE, "r+"); ++ if (fp == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "get proc file %s failed.\n", COLD_PAGE); ++ return -1; ++ } ++ ++ if (etmemd_send_ioctl_cmd(fp, &ioctl_para) != 0) { ++ fclose(fp); ++ etmemd_log(ETMEMD_LOG_ERR, "set_swapcache_wmark for pid %u fail\n", tk_pid->pid); ++ return -1; ++ } ++ ++ fclose(fp); ++ return 0; ++} ++ ++int etmemd_reclaim_swapcache(const struct task_pid *tk_pid) ++{ ++ char pid_str[PID_STR_MAX_LEN] = {0}; ++ FILE *fp = NULL; ++ struct ioctl_para ioctl_para = { ++ .ioctl_cmd = RECLAIM_SWAPCACHE_ON, ++ .ioctl_parameter = 0, ++ }; ++ ++ if (tk_pid == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "tk_pid is null.\n"); ++ return -1; ++ } ++ ++ if (!check_should_reclaim_swapcache(tk_pid)) { ++ return 0; ++ } ++ ++ if (snprintf_s(pid_str, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%u", tk_pid->pid) <= 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "snprintf pid fail %u", tk_pid->pid); ++ return -1; ++ } ++ ++ if (!tk_pid->tk->eng->proj->wmark_set) { ++ set_swapcache_wmark(tk_pid, pid_str); ++ tk_pid->tk->eng->proj->wmark_set = true; ++ } ++ ++ fp = etmemd_get_proc_file(pid_str, COLD_PAGE, "r+"); ++ if (fp == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "get proc file %s fail.\n", COLD_PAGE); ++ return -1; ++ } ++ ++ if (etmemd_send_ioctl_cmd(fp, &ioctl_para) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "etmemd_reclaim_swapcache fail\n"); ++ fclose(fp); ++ return -1; ++ } ++ ++ fclose(fp); ++ return 0; ++} + + int etmemd_grade_migrate(const char *pid, const struct memory_grade *memory_grade) + { +diff --git a/etmem/src/etmemd_src/etmemd_project.c b/etmem/src/etmemd_src/etmemd_project.c +index 459e140..72d7335 100644 +--- a/etmem/src/etmemd_src/etmemd_project.c ++++ b/etmem/src/etmemd_src/etmemd_project.c +@@ -639,19 +639,64 @@ static int fill_project_sysmem_threshold(void *obj, void *val) + int sysmem_threshold = parse_to_int(val); + + if (sysmem_threshold < 0 || sysmem_threshold > MAX_SYSMEM_THRESHOLD_VALUE) { +- etmemd_log(ETMEMD_LOG_WARN, "invaild project sysmem_threshold value %d, it must between 0 and 100.\n", +- sysmem_threshold, MAX_SYSMEM_THRESHOLD_VALUE); +- sysmem_threshold = -1; ++ etmemd_log(ETMEMD_LOG_ERR, "invaild project sysmem_threshold value %d, it must between 0 and 100.\n", ++ sysmem_threshold); ++ return -1; + } + + proj->sysmem_threshold = sysmem_threshold; + return 0; + } + ++/* fill the project parameter: swapcache_low_wmark ++ * swapcache_low_wmark: [0, 100]. */ ++static int fill_project_swapcache_low_wmark(void *obj, void *val) ++{ ++ struct project *proj = (struct project *)obj; ++ int swapcache_low_wmark = parse_to_int(val); ++ ++ if (swapcache_low_wmark < 0 || swapcache_low_wmark > MAX_SWAPCACHE_WMARK_VALUE) { ++ etmemd_log(ETMEMD_LOG_ERR, "invaild project swapcache_low_wmark value %d, it must between 0 and 100.\n", ++ swapcache_low_wmark); ++ return -1; ++ } ++ ++ proj->swapcache_low_wmark = swapcache_low_wmark; ++ return 0; ++} ++ ++/* fill the project parameter: swapcache_high_wmark ++ * swapcache_high_wmark: (0, 100]. */ ++static int fill_project_swapcache_high_wmark(void *obj, void *val) ++{ ++ struct project *proj = (struct project *)obj; ++ int swapcache_high_wmark = parse_to_int(val); ++ ++ if (swapcache_high_wmark < 0 || swapcache_high_wmark > MAX_SWAPCACHE_WMARK_VALUE) { ++ etmemd_log(ETMEMD_LOG_ERR, "invaild project swapcache_high_wmark value %d, it must between 0 and 100.\n", ++ swapcache_high_wmark); ++ return -1; ++ } ++ ++ proj->swapcache_high_wmark = swapcache_high_wmark; ++ return 0; ++} ++ ++static bool check_swapcache_wmark_valid(struct project *proj) ++{ ++ if (proj->swapcache_low_wmark > proj->swapcache_high_wmark) { ++ return false; ++ } ++ ++ return true; ++} ++ + static struct config_item g_project_config_items[] = { + {"name", STR_VAL, fill_project_name, false}, + {"scan_type", STR_VAL, fill_project_scan_type, false}, + {"sysmem_threshold", INT_VAL, fill_project_sysmem_threshold, true}, ++ {"swapcache_high_wmark", INT_VAL, fill_project_swapcache_high_wmark, true}, ++ {"swapcache_low_wmark", INT_VAL, fill_project_swapcache_low_wmark, true}, + }; + + static void clear_project(struct project *proj) +@@ -675,6 +720,11 @@ static int project_fill_by_conf(GKeyFile *config, struct project *proj) + return -1; + } + ++ if (!check_swapcache_wmark_valid(proj)) { ++ etmemd_log(ETMEMD_LOG_ERR, "swapcache wmark is not valid, low wmark: %d, high wmark: %d", ++ proj->swapcache_low_wmark, proj->swapcache_high_wmark); ++ return -1; ++ } + return 0; + } + +diff --git a/etmem/src/etmemd_src/etmemd_scan.c b/etmem/src/etmemd_src/etmemd_scan.c +index 3ee018e..a1f8cdc 100644 +--- a/etmem/src/etmemd_src/etmemd_scan.c ++++ b/etmem/src/etmemd_src/etmemd_scan.c +@@ -359,7 +359,7 @@ struct vmas *get_vmas_with_flags(const char *pid, char *vmflags_array[], int vmf + return NULL; + } + +- fp = etmemd_get_proc_file(pid, maps_file, 0, "r"); ++ fp = etmemd_get_proc_file(pid, maps_file, "r"); + if (fp == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "open %s file of %s fail\n", maps_file, pid); + free(ret_vmas); +@@ -680,13 +680,23 @@ int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **p + struct vma *vma = vmas->vma_list; + struct page_refs **tmp_page_refs = NULL; + struct walk_address walk_address = {0, 0, 0}; ++ struct ioctl_para ioctl_para = { ++ .ioctl_cmd = IDLE_SCAN_ADD_FLAGS, ++ .ioctl_parameter = flags, ++ }; + +- scan_fp = etmemd_get_proc_file(pid, IDLE_SCAN_FILE, flags, "r"); ++ scan_fp = etmemd_get_proc_file(pid, IDLE_SCAN_FILE, "r"); + if (scan_fp == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "open %s file fail\n", IDLE_SCAN_FILE); + return -1; + } + ++ if (flags != 0 && etmemd_send_ioctl_cmd(scan_fp, &ioctl_para) != 0) { ++ fclose(scan_fp); ++ etmemd_log(ETMEMD_LOG_ERR, "etmemd_send_ioctl_cmd %s file for pid %s fail\n", IDLE_SCAN_FILE, pid); ++ return -1; ++ } ++ + fd = fileno(scan_fp); + if (fd == -1) { + etmemd_log(ETMEMD_LOG_ERR, "fileno file fail\n"); +diff --git a/etmem/src/etmemd_src/etmemd_slide.c b/etmem/src/etmemd_src/etmemd_slide.c +index cbc4b17..c478fbd 100644 +--- a/etmem/src/etmemd_src/etmemd_slide.c ++++ b/etmem/src/etmemd_src/etmemd_slide.c +@@ -256,6 +256,10 @@ scan_out: + etmemd_log(ETMEMD_LOG_DEBUG, "slide migrate for pid %u fail\n", tk_pid->pid); + } + ++ if (etmemd_reclaim_swapcache(tk_pid) != 0) { ++ etmemd_log(ETMEMD_LOG_DEBUG, "etmemd_reclaim_swapcache pid %u fail\n", tk_pid->pid); ++ } ++ + exit: + /* clean memory_grade here */ + pthread_cleanup_pop(1); +-- +1.8.3.1 + diff --git a/0068-etmem-add-swap-flag-to-support-specified-page-swap-o.patch b/0068-etmem-add-swap-flag-to-support-specified-page-swap-o.patch new file mode 100644 index 0000000000000000000000000000000000000000..5d37fcdf8c87c9e53ed0ead5b3814dd7722fd796 --- /dev/null +++ b/0068-etmem-add-swap-flag-to-support-specified-page-swap-o.patch @@ -0,0 +1,434 @@ +From d6e4942b34bbcbfaec8b0d4702f0e385f8d267f1 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Tue, 18 Jan 2022 15:55:29 +0800 +Subject: [PATCH 18/33] etmem: add swap flag to support specified page swap out + +The existing memory expansion tool etmem swaps out +all pages that can be swapped out for the process by +default, unless the page is marked with lock flag. + +The function of swapping out specified pages is add. +The process adds special flag for pages to be swapped +out. This function depends on etmem_scan module. + +Added swap_flag field to indicate that a tagged swap +out is used for this process instead of the default +swap out. + +Signed-off-by: liubo +--- + etmem/conf/slide_conf.yaml | 1 + + etmem/inc/etmemd_inc/etmemd_common.h | 14 +++----------- + etmem/inc/etmemd_inc/etmemd_scan.h | 9 +++++++-- + etmem/inc/etmemd_inc/etmemd_scan_exp.h | 1 + + etmem/inc/etmemd_inc/etmemd_slide.h | 7 ++++++- + etmem/inc/etmemd_inc/etmemd_task_exp.h | 1 + + etmem/src/etmemd_src/etmemd_common.c | 34 +++++++++++++++++++--------------- + etmem/src/etmemd_src/etmemd_migrate.c | 8 ++++++-- + etmem/src/etmemd_src/etmemd_scan.c | 24 ++++++++++++++++-------- + etmem/src/etmemd_src/etmemd_slide.c | 12 ++++++------ + etmem/src/etmemd_src/etmemd_task.c | 23 +++++++++++++++++++++++ + 11 files changed, 89 insertions(+), 45 deletions(-) + +diff --git a/etmem/conf/slide_conf.yaml b/etmem/conf/slide_conf.yaml +index f55c508..8169b7d 100644 +--- a/etmem/conf/slide_conf.yaml ++++ b/etmem/conf/slide_conf.yaml +@@ -21,3 +21,4 @@ value=mysql + T=1 + max_threads=1 + swap_threshold=10g ++swap_flag=yes +diff --git a/etmem/inc/etmemd_inc/etmemd_common.h b/etmem/inc/etmemd_inc/etmemd_common.h +index ced606e..03792a7 100644 +--- a/etmem/inc/etmemd_inc/etmemd_common.h ++++ b/etmem/inc/etmemd_inc/etmemd_common.h +@@ -34,7 +34,7 @@ + + #define BYTE_TO_KB(s) ((s) >> 10) + #define KB_TO_BYTE(s) ((s) << 10) +-#define CONVERT_GB_2_KB (1024 * 1024) ++#define GB_TO_KB(s) ((s) << 20) + + #define MAX_SWAPCACHE_WMARK_VALUE 100 + +@@ -46,17 +46,9 @@ + + #define PIPE_FD_LEN 2 + +-#define IDLE_SCAN_MAGIC 0x66 +-#define IDLE_SCAN_ADD_FLAGS _IOW(IDLE_SCAN_MAGIC, 0x0, unsigned int) +- +-enum swap_type { +- DONT_SWAP = 0, +- DO_SWAP, +-}; +- + struct ioctl_para { + unsigned long ioctl_cmd; +- int ioctl_parameter; ++ unsigned int ioctl_parameter; + }; + + /* +@@ -87,6 +79,6 @@ int get_mem_from_proc_file(const char *pid, const char *file_name, unsigned long + + int dprintf_all(int fd, const char *format, ...); + +-int get_swap_threshold_inKB(char *string); ++int get_swap_threshold_inKB(const char *string, unsigned long *value); + + #endif +diff --git a/etmem/inc/etmemd_inc/etmemd_scan.h b/etmem/inc/etmemd_inc/etmemd_scan.h +index 9e5bcc4..7c25152 100644 +--- a/etmem/inc/etmemd_inc/etmemd_scan.h ++++ b/etmem/inc/etmemd_inc/etmemd_scan.h +@@ -20,6 +20,7 @@ + #include "etmemd.h" + #include "etmemd_task.h" + #include "etmemd_scan_exp.h" ++#include "etmemd_common.h" + + #define VMA_SEG_CNT_MAX 6 + #define VMA_PERMS_STR_LEN 5 +@@ -34,7 +35,10 @@ + #define SMAPS_FILE "/smaps" + #define VMFLAG_HEAD "VmFlags" + +-#define ALL_SCAN_FLAGS (SCAN_AS_HUGE | SCAN_IGN_HOST) ++#define IDLE_SCAN_MAGIC 0x66 ++#define IDLE_SCAN_ADD_FLAGS _IOW(IDLE_SCAN_MAGIC, 0x0, unsigned int) ++#define VMA_SCAN_ADD_FLAGS _IOW(IDLE_SCAN_MAGIC, 0x2, unsigned int) ++#define ALL_SCAN_FLAGS (SCAN_AS_HUGE | SCAN_IGN_HOST | VMA_SCAN_FLAG) + + enum page_idle_type { + PTE_ACCESS = 0, /* 4k page */ +@@ -70,7 +74,8 @@ struct page_refs *etmemd_do_scan(const struct task_pid *tpid, const struct task + void free_vmas(struct vmas *vmas); + + struct page_refs **walk_vmas(int fd, struct walk_address *walk_address, struct page_refs **pf, unsigned long *use_rss); +-int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **page_refs, unsigned long *use_rss, int flags); ++int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **page_refs, ++ unsigned long *use_rss, struct ioctl_para *ioctl_para); + + int split_vmflags(char ***vmflags_array, char *vmflags); + struct vmas *get_vmas_with_flags(const char *pid, char **vmflags_array, int vmflags_num, bool is_anon_only); +diff --git a/etmem/inc/etmemd_inc/etmemd_scan_exp.h b/etmem/inc/etmemd_inc/etmemd_scan_exp.h +index 1fd4379..7be925c 100644 +--- a/etmem/inc/etmemd_inc/etmemd_scan_exp.h ++++ b/etmem/inc/etmemd_inc/etmemd_scan_exp.h +@@ -25,6 +25,7 @@ + + #define SCAN_AS_HUGE 0100000000 /* treat normal vm page as vm hugepage */ + #define SCAN_IGN_HOST 0200000000 /* ignore host access when scan vm */ ++#define VMA_SCAN_FLAG 0x1000 /* scan the specifics vma with flag */ + + enum { + VMA_STAT_READ = 0, +diff --git a/etmem/inc/etmemd_inc/etmemd_slide.h b/etmem/inc/etmemd_inc/etmemd_slide.h +index 7c80502..726c721 100644 +--- a/etmem/inc/etmemd_inc/etmemd_slide.h ++++ b/etmem/inc/etmemd_inc/etmemd_slide.h +@@ -22,10 +22,15 @@ + struct slide_params { + struct task_executor *executor; + int t; /* watermark */ +- int swap_threshold; ++ unsigned long swap_threshold; + uint8_t dram_percent; + }; + ++enum swap_type { ++ DONT_SWAP = 0, ++ DO_SWAP, ++}; ++ + int fill_engine_type_slide(struct engine *eng, GKeyFile *config); + + #endif +diff --git a/etmem/inc/etmemd_inc/etmemd_task_exp.h b/etmem/inc/etmemd_inc/etmemd_task_exp.h +index 33d505a..6f775b6 100644 +--- a/etmem/inc/etmemd_inc/etmemd_task_exp.h ++++ b/etmem/inc/etmemd_inc/etmemd_task_exp.h +@@ -29,6 +29,7 @@ struct task { + char *value; + char *name; + int max_threads; ++ int swap_flag; + + struct task_pid *pids; + struct engine *eng; +diff --git a/etmem/src/etmemd_src/etmemd_common.c b/etmem/src/etmemd_src/etmemd_common.c +index bb72fd0..dfbae6d 100644 +--- a/etmem/src/etmemd_src/etmemd_common.c ++++ b/etmem/src/etmemd_src/etmemd_common.c +@@ -261,7 +261,7 @@ static char *etmemd_get_proc_file_str(const char *pid, const char *file) + } + + if (snprintf_s(file_name, file_str_size, file_str_size - 1, +- "%s%s%s", PROC_PATH, pid ? pid : "", file) == -1) { ++ "%s%s%s", PROC_PATH, pid == NULL ? "" : pid, file) == -1) { + etmemd_log(ETMEMD_LOG_ERR, "snprintf for %s fail\n", file); + free(file_name); + return NULL; +@@ -274,8 +274,8 @@ int etmemd_send_ioctl_cmd(FILE *fp, struct ioctl_para *request) + { + int fd = -1; + +- if (fp == NULL) { +- etmemd_log(ETMEMD_LOG_ERR, "send ioctl cmd fail, fp is null\n"); ++ if (fp == NULL || request == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "send ioctl cmd fail, para is null\n"); + return -1; + } + +@@ -285,8 +285,8 @@ int etmemd_send_ioctl_cmd(FILE *fp, struct ioctl_para *request) + return -1; + } + +- if (request == NULL || ioctl(fd, request->ioctl_cmd, &request->ioctl_parameter) != 0) { +- etmemd_log(ETMEMD_LOG_ERR, "send ioctl cmd fail, request is wrong\n"); ++ if (ioctl(fd, request->ioctl_cmd, &request->ioctl_parameter) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "ioctl failed\n"); + return -1; + } + +@@ -298,6 +298,11 @@ FILE *etmemd_get_proc_file(const char *pid, const char *file, const char *mode) + char *file_name = NULL; + FILE *fp = NULL; + ++ if (file == NULL) { ++ etmemd_log(ETMEMD_LOG_ERR, "etmemd_get_proc_file file should not be NULL\n"); ++ return NULL; ++ } ++ + file_name = etmemd_get_proc_file_str(pid, file); + if (file_name == NULL) { + return NULL; +@@ -498,22 +503,21 @@ unsigned long get_pagesize(void) + return (unsigned long)pagesize; + } + +-int get_swap_threshold_inKB(char *string) ++int get_swap_threshold_inKB(const char *string, unsigned long *value) + { + int len; + int i; + int ret = -1; + char *swap_threshold_string = NULL; +- int swap_threshold_inGB; +- int swap_threshold_inKB; ++ unsigned long swap_threshold_inGB; + +- if (string == NULL) { ++ if (string == NULL || value == NULL) { + goto out; + } + + len = strlen(string); +- if (len > SWAP_THRESHOLD_MAX_LEN) { +- etmemd_log(ETMEMD_LOG_ERR, "swap_threshold string is too long.\n"); ++ if (len == 0 || len > SWAP_THRESHOLD_MAX_LEN) { ++ etmemd_log(ETMEMD_LOG_ERR, "swap_threshold string is invalid.\n"); + goto out; + } + +@@ -537,13 +541,13 @@ int get_swap_threshold_inKB(char *string) + goto free_out; + } + +- if (get_int_value(swap_threshold_string, &swap_threshold_inGB) != 0) { +- etmemd_log(ETMEMD_LOG_ERR, "get_int_value swap_threshold faild.\n"); ++ if (get_unsigned_long_value(swap_threshold_string, &swap_threshold_inGB) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "get_unsigned_long_value swap_threshold faild.\n"); + goto free_out; + } + +- swap_threshold_inKB = swap_threshold_inGB * CONVERT_GB_2_KB; +- ret = swap_threshold_inKB; ++ *value = GB_TO_KB(swap_threshold_inGB); ++ ret = 0; + + free_out: + free(swap_threshold_string); +diff --git a/etmem/src/etmemd_src/etmemd_migrate.c b/etmem/src/etmemd_src/etmemd_migrate.c +index 87bfde0..a5cce41 100644 +--- a/etmem/src/etmemd_src/etmemd_migrate.c ++++ b/etmem/src/etmemd_src/etmemd_migrate.c +@@ -131,7 +131,8 @@ static bool check_should_reclaim_swapcache(const struct task_pid *tk_pid) + return false; + } + +- if ((swapcache_total / proj->swapcache_high_wmark) <= (mem_total / MAX_SWAPCACHE_WMARK_VALUE)) { ++ if (swapcache_total == 0 || ++ (mem_total / swapcache_total) >= (unsigned long)(MAX_SWAPCACHE_WMARK_VALUE / proj->swapcache_high_wmark)) { + return false; + } + +@@ -190,7 +191,10 @@ int etmemd_reclaim_swapcache(const struct task_pid *tk_pid) + } + + if (!tk_pid->tk->eng->proj->wmark_set) { +- set_swapcache_wmark(tk_pid, pid_str); ++ if (set_swapcache_wmark(tk_pid, pid_str) != 0) { ++ etmemd_log(ETMEMD_LOG_ERR, "set_swapcache_wmark for pid %u fail\n", tk_pid->pid); ++ return -1; ++ } + tk_pid->tk->eng->proj->wmark_set = true; + } + +diff --git a/etmem/src/etmemd_src/etmemd_scan.c b/etmem/src/etmemd_src/etmemd_scan.c +index a1f8cdc..e06ba92 100644 +--- a/etmem/src/etmemd_src/etmemd_scan.c ++++ b/etmem/src/etmemd_src/etmemd_scan.c +@@ -672,7 +672,8 @@ struct page_refs **walk_vmas(int fd, + * this parameter is used only in the dynamic engine to calculate the swap-in rate. + * In other policies, NULL can be directly transmitted. + * */ +-int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **page_refs, unsigned long *use_rss, int flags) ++int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **page_refs, ++ unsigned long *use_rss, struct ioctl_para *ioctl_para) + { + u_int64_t i; + FILE *scan_fp = NULL; +@@ -680,10 +681,6 @@ int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **p + struct vma *vma = vmas->vma_list; + struct page_refs **tmp_page_refs = NULL; + struct walk_address walk_address = {0, 0, 0}; +- struct ioctl_para ioctl_para = { +- .ioctl_cmd = IDLE_SCAN_ADD_FLAGS, +- .ioctl_parameter = flags, +- }; + + scan_fp = etmemd_get_proc_file(pid, IDLE_SCAN_FILE, "r"); + if (scan_fp == NULL) { +@@ -691,7 +688,8 @@ int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **p + return -1; + } + +- if (flags != 0 && etmemd_send_ioctl_cmd(scan_fp, &ioctl_para) != 0) { ++ if (ioctl_para != NULL && ioctl_para->ioctl_parameter != 0 ++ && etmemd_send_ioctl_cmd(scan_fp, ioctl_para) != 0) { + fclose(scan_fp); + etmemd_log(ETMEMD_LOG_ERR, "etmemd_send_ioctl_cmd %s file for pid %s fail\n", IDLE_SCAN_FILE, pid); + return -1; +@@ -734,6 +732,7 @@ int get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **p + + int etmemd_get_page_refs(const struct vmas *vmas, const char *pid, struct page_refs **page_refs, int flags) + { ++ struct ioctl_para ioctl_para; + if (!g_exp_scan_inited) { + etmemd_log(ETMEMD_LOG_ERR, "scan module is not inited before etmemd_get_page_refs\n"); + return -1; +@@ -744,7 +743,10 @@ int etmemd_get_page_refs(const struct vmas *vmas, const char *pid, struct page_r + return -1; + } + +- return get_page_refs(vmas, pid, page_refs, NULL, flags & ALL_SCAN_FLAGS); ++ ioctl_para.ioctl_parameter = flags & ALL_SCAN_FLAGS; ++ ioctl_para.ioctl_cmd = IDLE_SCAN_ADD_FLAGS; ++ ++ return get_page_refs(vmas, pid, page_refs, NULL, &ioctl_para); + } + + void etmemd_free_page_refs(struct page_refs *pf) +@@ -765,6 +767,7 @@ struct page_refs *etmemd_do_scan(const struct task_pid *tpid, const struct task + struct page_refs *page_refs = NULL; + int ret; + char pid[PID_STR_MAX_LEN] = {0}; ++ struct ioctl_para ioctl_para = {0}; + + if (tk == NULL) { + etmemd_log(ETMEMD_LOG_ERR, "task struct is null for pid %u\n", tpid->pid); +@@ -785,9 +788,14 @@ struct page_refs *etmemd_do_scan(const struct task_pid *tpid, const struct task + return NULL; + } + ++ ioctl_para.ioctl_cmd = VMA_SCAN_ADD_FLAGS; ++ if (tk->swap_flag != 0) { ++ ioctl_para.ioctl_parameter = VMA_SCAN_FLAG; ++ } ++ + /* loop for scanning idle_pages to get result of memory access. */ + for (i = 0; i < page_scan->loop; i++) { +- ret = get_page_refs(vmas, pid, &page_refs, NULL, 0); ++ ret = get_page_refs(vmas, pid, &page_refs, NULL, &ioctl_para); + if (ret != 0) { + etmemd_log(ETMEMD_LOG_ERR, "scan operation failed\n"); + /* free page_refs nodes already exist */ +diff --git a/etmem/src/etmemd_src/etmemd_slide.c b/etmem/src/etmemd_src/etmemd_slide.c +index c478fbd..236778a 100644 +--- a/etmem/src/etmemd_src/etmemd_slide.c ++++ b/etmem/src/etmemd_src/etmemd_slide.c +@@ -185,7 +185,7 @@ static int check_pidmem_lower_threshold(struct task_pid *tk_pid) + return check_pid_should_swap(pid_str, vmrss, tk_pid); + } + +- if ((int)vmrss > params->swap_threshold) { ++ if (vmrss > params->swap_threshold) { + return DO_SWAP; + } + +@@ -305,16 +305,16 @@ static int fill_task_swap_threshold(void *obj, void *val) + { + struct slide_params *params = (struct slide_params *)obj; + char *swap_threshold_string = (char *)val; +- int swap_threshold = get_swap_threshold_inKB(swap_threshold_string); ++ unsigned long swap_threshold; + +- free(swap_threshold_string); +- +- if (swap_threshold < 0) { ++ if (get_swap_threshold_inKB(swap_threshold_string, &swap_threshold) != 0) { + etmemd_log(ETMEMD_LOG_WARN, + "parse swap_threshold failed.\n"); ++ free(swap_threshold_string); + return -1; + } +- ++ ++ free(swap_threshold_string); + params->swap_threshold = swap_threshold; + + return 0; +diff --git a/etmem/src/etmemd_src/etmemd_task.c b/etmem/src/etmemd_src/etmemd_task.c +index 618245e..2a8cb3e 100644 +--- a/etmem/src/etmemd_src/etmemd_task.c ++++ b/etmem/src/etmemd_src/etmemd_task.c +@@ -470,10 +470,33 @@ static int fill_task_threads(void *obj, void *val) + return 0; + } + ++static int fill_task_swap_flag(void *obj, void *val) ++{ ++ struct task *tk = (struct task *)obj; ++ char *swap_flag = (char *)val; ++ ++ if (strcmp(swap_flag, "yes") == 0) { ++ tk->swap_flag = 1; ++ free(val); ++ return 0; ++ } ++ ++ if (strcmp(swap_flag, "no") == 0) { ++ tk->swap_flag = 0; ++ free(val); ++ return 0; ++ } ++ ++ free(val); ++ etmemd_log(ETMEMD_LOG_ERR, "swap_flag para is not valid.\n"); ++ return -1; ++} ++ + struct config_item g_task_config_items[] = { + {"name", STR_VAL, fill_task_name, false}, + {"type", STR_VAL, fill_task_type, false}, + {"value", STR_VAL, fill_task_value, false}, ++ {"swap_flag", STR_VAL, fill_task_swap_flag, true}, + {"max_threads", INT_VAL, fill_task_threads, true}, + }; + +-- +1.8.3.1 + diff --git a/0069-etmem-fix-the-swapcache-wmark-configuration-parse-er.patch b/0069-etmem-fix-the-swapcache-wmark-configuration-parse-er.patch new file mode 100644 index 0000000000000000000000000000000000000000..1b6a0340f2996a9aacb38f2efe7ca7cc180ca16c --- /dev/null +++ b/0069-etmem-fix-the-swapcache-wmark-configuration-parse-er.patch @@ -0,0 +1,93 @@ +From fff3255965293f42b9b6af79d0766110411c49d4 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Sat, 12 Feb 2022 10:15:28 +0800 +Subject: [PATCH 19/33] etmem: fix the swapcache wmark configuration parse + error + +swapcache_high_wmark and swapcache_low_wmark should +appear in pairs, missing either part should report +an error. +In addition, swapcache_high_wmark should be greater +than swapcache_low_wmark. + +Signed-off-by: liubo +--- + etmem/src/etmemd_src/etmemd_migrate.c | 2 +- + etmem/src/etmemd_src/etmemd_project.c | 20 ++++++++++++++------ + 2 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/etmem/src/etmemd_src/etmemd_migrate.c b/etmem/src/etmemd_src/etmemd_migrate.c +index a5cce41..a143c5e 100644 +--- a/etmem/src/etmemd_src/etmemd_migrate.c ++++ b/etmem/src/etmemd_src/etmemd_migrate.c +@@ -115,7 +115,7 @@ static bool check_should_reclaim_swapcache(const struct task_pid *tk_pid) + unsigned long swapcache_total; + int ret; + +- if (proj->swapcache_high_wmark == 0) { ++ if (proj->swapcache_high_wmark == -1 || proj->swapcache_low_wmark == -1) { + return false; + } + +diff --git a/etmem/src/etmemd_src/etmemd_project.c b/etmem/src/etmemd_src/etmemd_project.c +index 72d7335..e238e66 100644 +--- a/etmem/src/etmemd_src/etmemd_project.c ++++ b/etmem/src/etmemd_src/etmemd_project.c +@@ -649,13 +649,13 @@ static int fill_project_sysmem_threshold(void *obj, void *val) + } + + /* fill the project parameter: swapcache_low_wmark +- * swapcache_low_wmark: [0, 100]. */ ++ * swapcache_low_wmark: (0, 100]. */ + static int fill_project_swapcache_low_wmark(void *obj, void *val) + { + struct project *proj = (struct project *)obj; + int swapcache_low_wmark = parse_to_int(val); + +- if (swapcache_low_wmark < 0 || swapcache_low_wmark > MAX_SWAPCACHE_WMARK_VALUE) { ++ if (swapcache_low_wmark <= 0 || swapcache_low_wmark > MAX_SWAPCACHE_WMARK_VALUE) { + etmemd_log(ETMEMD_LOG_ERR, "invaild project swapcache_low_wmark value %d, it must between 0 and 100.\n", + swapcache_low_wmark); + return -1; +@@ -672,7 +672,7 @@ static int fill_project_swapcache_high_wmark(void *obj, void *val) + struct project *proj = (struct project *)obj; + int swapcache_high_wmark = parse_to_int(val); + +- if (swapcache_high_wmark < 0 || swapcache_high_wmark > MAX_SWAPCACHE_WMARK_VALUE) { ++ if (swapcache_high_wmark <= 0 || swapcache_high_wmark > MAX_SWAPCACHE_WMARK_VALUE) { + etmemd_log(ETMEMD_LOG_ERR, "invaild project swapcache_high_wmark value %d, it must between 0 and 100.\n", + swapcache_high_wmark); + return -1; +@@ -684,11 +684,17 @@ static int fill_project_swapcache_high_wmark(void *obj, void *val) + + static bool check_swapcache_wmark_valid(struct project *proj) + { +- if (proj->swapcache_low_wmark > proj->swapcache_high_wmark) { +- return false; ++ if (proj->swapcache_high_wmark == -1 && proj->swapcache_low_wmark == -1) { ++ return true; + } + +- return true; ++ if ((proj->swapcache_high_wmark > 0) && ++ (proj->swapcache_low_wmark > 0) && ++ (proj->swapcache_high_wmark > proj->swapcache_low_wmark)) { ++ return true; ++ } ++ ++ return false; + } + + static struct config_item g_project_config_items[] = { +@@ -759,6 +765,8 @@ enum opt_result etmemd_project_add(GKeyFile *config) + } + + proj->sysmem_threshold = -1; ++ proj->swapcache_high_wmark = -1; ++ proj->swapcache_low_wmark = -1; + + if (project_fill_by_conf(config, proj) != 0) { + etmemd_log(ETMEMD_LOG_ERR, "fill project from configuration file fail\n"); +-- +1.8.3.1 + diff --git a/0070-etmem-update-README.md.patch b/0070-etmem-update-README.md.patch new file mode 100644 index 0000000000000000000000000000000000000000..df263eea4132193a59de867e693ce9b03ea979c8 --- /dev/null +++ b/0070-etmem-update-README.md.patch @@ -0,0 +1,108 @@ +From 1ebeebf02a171d0029e70ee67270a8f7dab3e04e Mon Sep 17 00:00:00 2001 +From: liubo +Date: Thu, 24 Feb 2022 01:13:17 +0000 +Subject: [PATCH 20/33] etmem: update README.md. + +Add the usage constraints of etmem, +and introduce some added configuration file parameters + +Signed-off-by: liubo +--- + README.md | 45 ++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 40 insertions(+), 5 deletions(-) + +diff --git a/README.md b/README.md +index 93631a1..49287f9 100644 +--- a/README.md ++++ b/README.md +@@ -29,6 +29,30 @@ etmem内存分级扩展技术,通过DRAM+内存压缩/高性能存储新介质 + $ make + + ++## 注意事项 ++### 运行依赖 ++etmem作为内存扩展工具,需要依赖于内核态的特性支持,为了可以识别内存访问情况和支持主动将内存写入swap分区来达到内存垂直扩展的需求,etmem在运行时需要插入etmem_scan和etmem_swap模块: ++ ++``` ++modprobe etmem_scan ++modprobe etmem_swap ++``` ++openuler21.03、21.09、20.03 LTS SP2以及20.03 LTS SP3均支持etmem内存扩展相关特性,可以直接使用以上内核。 ++ ++### 权限限制 ++运行etmem进程需要root权限,root用户具有系统最高权限,在使用root用户进行操作时,请严格按照操作指导进行操作,避免其他操作造成系统管理及安全风险。 ++ ++### 使用约束 ++ ++- etmem的客户端和服务端需要在同一个服务器上部署,不支持跨服务器通信的场景。 ++- etmem仅支持扫描进程名小于或等于15个字符长度的目标进程。 ++- 在使用AEP介质进行内存扩展的时候,依赖于系统可以正确识别AEP设备并将AEP设备初始化为numa node。并且配置文件中的vm_flags字段只能配置为ht。 ++- 引擎私有命令仅针对对应引擎和引擎下的任务有效,比如cslide所支持的showhostpages和showtaskpages。 ++- 第三方策略实现代码中,eng_mgt_func接口中的fd不能写入0xff和0xfe字。 ++- 支持在一个工程内添加多个不同的第三方策略动态库,以配置文件中的eng_name来区分。 ++- 禁止并发扫描同一个进程。未加载etmem_scan和etmem_swap ko时,禁止使用/proc/xxx/idle_pages和/proc/xxx/swap_pages文件 ++ ++ + ## 使用说明 + + ### 启动etmemd进程 +@@ -63,7 +87,14 @@ options: + + 在运行etmem进程之前,需要管理员预先规划哪些进程需要做内存扩展,将进程信息配置到etmem配置文件中,并配置内存扫描的周期、扫描次数、内存冷热阈值等信息。 + +-配置文件的示例文件在源码包中,放置在源码根目录的conf/example_conf.yaml,建议在使用时放置在/etc/etmem/目录下,示例内容为: ++配置文件的示例文件在源码包中,放置在/etc/etmem文件路径下,按照功能划分为3个示例文件, ++ ++``` ++/etc/etmem/cslide_conf.yaml ++/etc/etmem/slide_conf.yaml ++/etc/etmem/thirdparty_conf.yaml ++``` ++示例内容分别为: + + ``` + [project] +@@ -132,6 +163,9 @@ task_private_key=task_private_value + | loop | 内存扫描的循环次数 | 是 | 是 | 1~10 | loop=3 //扫描3次 | + | interval | 每次内存扫描的时间间隔 | 是 | 是 | 1~1200 | interval=5 //每次扫描之间间隔5s | + | sleep | 每个内存扫描+操作的大周期之间时间间隔 | 是 | 是 | 1~1200 | sleep=10 //每次大周期之间间隔10s | ++| sysmem_threshold| slide engine的配置项,系统内存换出阈值 | 否 | 是 | 0~100 | sysmem_threshold=50 //系统内存剩余量小于50%时,etmem才会触发内存换出| ++| swapcache_high_wmark| slide engine的配置项,swacache可以占用系统内存的比例,高水线 | 否 | 是 | 1~100 | swapcache_high_wmark=5 //swapcache内存占用量可以为系统内存的5%,超过该比例,etmem会触发swapcache回收
注: swapcache_high_wmark需要大于swapcache_low_wmark| ++| swapcache_low_wmark| slide engine的配置项,swacache可以占用系统内存的比例,低水线 | 否 | 是 | [1~swapcache_high_wmark) | swapcache_low_wmark=3 //触发swapcache回收后,系统会将swapcache内存占用量回收到低于3%| + | [engine] | engine公用配置段起始标识 | 否 | 否 | NA | engine参数的开头标识,表示下面的参数直到另外的[xxx]或文件结尾为止的范围内均为engine section的参数 | + | project | 声明所在的project | 是 | 是 | 64个字以内的字符串 | 已经存在名字为test的project,则可以写为project=test | + | engine | 声明所在的engine | 是 | 是 | slide/cslide/thridparty | 声明使用的是slide或cslide或thirdparty策略 | +@@ -155,7 +189,8 @@ task_private_key=task_private_value + | anon_only | engine为cslide的task配置项,标识是否只扫描匿名页 | 否 | 是 | yes/no | anon_only=no //配置为yes时只扫描匿名页,配置为no时非匿名页也会扫描 | + | ign_host | engine为cslide的task配置项,标识是否忽略host上的页表扫描信息 | 否 | 是 | yes/no | ign_host=no //yes为忽略,no为不忽略 | + | task_private_key | engine为thirdparty的task配置项,预留给第三方策略的task解析私有参数的配置项,选配 | 否 | 否 | 根据第三方策略私有参数自行限制 | 根据第三方策略私有task参数自行配置 | +- ++| swap_threshold |slide engine的配置项,进程内存换出阈值 | 否 | 是 | 进程可用内存绝对值 | swap_threshold=10g //进程占用内存在低于10g时不会触发换出。
当前版本下,仅支持g/G作为内存绝对值单位。与sysmem_threshold配合使用,仅系统内存低于阈值时,进行白名单中进程阈值判断 | ++| swap_flag|slide engine的配置项,进程指定内存换出 | 否 | 是 | yes/no | swap_flag=yes//使能进程指定内存换出 | + + + ### etmem project/engine/task对象的创建和删除 +@@ -172,11 +207,11 @@ task_private_key=task_private_value + + 添加对象: + +-etmem obj add -f /etc/example_config.yaml -s etmemd_socket ++etmem obj add -f /etc/etmem/slide_conf.yaml -s etmemd_socket + + 删除对象: + +-etmem obj del -f /etc/example_config.yaml -s etmemd_socket ++etmem obj del -f /etc/etmem/slide_conf.yaml -s etmemd_socket + + 打印帮助: + +@@ -491,4 +526,4 @@ etmem engine showhostpages -n proj_name -e cslide -s etmemd_socket + 1. Fork本仓库 + 2. 新建个人分支 + 3. 提交代码 +-4. 新建Pull Request +\ No newline at end of file ++4. 新建Pull Request +-- +1.8.3.1 + diff --git a/0071-etmem-add-code-of-testcase.patch b/0071-etmem-add-code-of-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..052bc2c188e37a12a94189a1004771afc49a6869 --- /dev/null +++ b/0071-etmem-add-code-of-testcase.patch @@ -0,0 +1,520 @@ +From 6847808d04c18a76db6bbf38ac6e421a5fac8b7c Mon Sep 17 00:00:00 2001 +From: liubo +Date: Mon, 24 Jan 2022 03:50:17 +0800 +Subject: [PATCH 21/33] etmem: add code of testcase + +add code of testcase of etmem socket functions. + +Signed-off-by: liubo +--- + etmem/test/conf/conf_cslide/task.config | 16 +- + etmem/test/etmem_migrate_ops_llt/CMakeLists.txt | 54 ++-- + .../etmem_migrate_ops_llt/etmem_migrate_ops_llt.c | 5 +- + .../test/etmem_socket_ops_llt_test/CMakeLists.txt | 26 ++ + .../etmem_socket_ops_llt.c | 356 +++++++++++++++++++++ + 5 files changed, 419 insertions(+), 38 deletions(-) + create mode 100644 etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_socket_ops_llt_test/etmem_socket_ops_llt.c + +diff --git a/etmem/test/conf/conf_cslide/task.config b/etmem/test/conf/conf_cslide/task.config +index 336be39..9719cb6 100644 +--- a/etmem/test/conf/conf_cslide/task.config ++++ b/etmem/test/conf/conf_cslide/task.config +@@ -1,9 +1,9 @@ +-[task] +-project=test +-engine=cslide +-name=background1 +-type=pid +-value=1 +-vm_flags=ht +-anon_only=no ++[task] ++project=test ++engine=cslide ++name=background1 ++type=pid ++value=1 ++vm_flags=ht ++anon_only=no + ign_host=yes +\ No newline at end of file +diff --git a/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt b/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt +index a9487af..d998af7 100644 +--- a/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt ++++ b/etmem/test/etmem_migrate_ops_llt/CMakeLists.txt +@@ -1,27 +1,27 @@ +-# /****************************************************************************** +-# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. +-# * etmem is licensed under the Mulan PSL v2. +-# * You can use this software according to the terms and conditions of the Mulan PSL v2. +-# * You may obtain a copy of Mulan PSL v2 at: +-# * http://license.coscl.org.cn/MulanPSL2 +-# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +-# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +-# * PURPOSE. +-# * See the Mulan PSL v2 for more details. +-# * Author: liubo +-# * Create: 2021-12-10 +-# * Description: CMakefileList for etmem_migrate_ops_llt to compile +-# ******************************************************************************/ +- +-project(etmem) +- +-INCLUDE_DIRECTORIES(../../inc/etmem_inc) +-INCLUDE_DIRECTORIES(../../inc/etmemd_inc) +-INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) +- +-SET(EXE etmem_migrate_ops_llt) +- +-add_executable(${EXE} etmem_migrate_ops_llt.c) +- +-set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,get_mem_from_proc_file") +-target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-10 ++# * Description: CMakefileList for etmem_migrate_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_migrate_ops_llt) ++ ++add_executable(${EXE} etmem_migrate_ops_llt.c) ++ ++set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,get_mem_from_proc_file") ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c b/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c +index 2758680..5c9b0d4 100644 +--- a/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c ++++ b/etmem/test/etmem_migrate_ops_llt/etmem_migrate_ops_llt.c +@@ -65,8 +65,7 @@ static struct memory_grade *get_memory_grade(void) + memory_grade = (struct memory_grade *)calloc(1, sizeof(struct memory_grade)); + CU_ASSERT_PTR_NOT_NULL(memory_grade); + +- while (page_refs != NULL) +- { ++ while (page_refs != NULL) { + if ((page_refs)->count >= WATER_LINE_TEMP) { + page_refs = add_page_refs_into_memory_grade(page_refs, &memory_grade->hot_pages); + continue; +@@ -104,7 +103,7 @@ static void test_etmem_migrate_ok(void) + + memory_grade = get_memory_grade(); + CU_ASSERT_PTR_NOT_NULL(memory_grade); +- CU_ASSERT_EQUAL(etmemd_grade_migrate("1", memory_grade), -1); ++ CU_ASSERT_EQUAL(etmemd_grade_migrate("1", memory_grade), 0); + + clean_memory_grade_unexpected(&memory_grade); + CU_ASSERT_PTR_NULL(memory_grade); +diff --git a/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..7cc5343 +--- /dev/null ++++ b/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,26 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-10 ++# * Description: CMakefileList for etmem_log_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_socket_ops_llt) ++ ++add_executable(${EXE} etmem_socket_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_socket_ops_llt_test/etmem_socket_ops_llt.c b/etmem/test/etmem_socket_ops_llt_test/etmem_socket_ops_llt.c +new file mode 100644 +index 0000000..387ffd1 +--- /dev/null ++++ b/etmem/test/etmem_socket_ops_llt_test/etmem_socket_ops_llt.c +@@ -0,0 +1,356 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-08-14 ++ * Description: This is a source file of the unit test for rpc functions in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmem_common.h" ++#include "etmem_rpc.h" ++#include "etmemd_rpc.h" ++#include "securec.h" ++#include "etmem.h" ++ ++#define SOCK_NAME_MAX_LEN 108 ++#define RPC_SEND_FILE_MAX 512 ++#define SLEEP_TIME_ONE_T_US 1000 ++ ++static char *get_length_str(unsigned int length) ++{ ++ char *result = NULL; ++ unsigned char i = 'a'; ++ unsigned int j; ++ result = (char *)calloc(length + 1, sizeof(char)); ++ if (result == NULL) { ++ return NULL; ++ } ++ ++ for (j = 0; j < length; j++) { ++ result[j] = i; ++ } ++ ++ return result; ++} ++ ++static void test_sock_name_error(void) ++{ ++ char *name = NULL; ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(NULL), -1); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(""), -1); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name("name"), 0); ++ ++ name = get_length_str(SOCK_NAME_MAX_LEN - 1); ++ CU_ASSERT_PTR_NOT_NULL(name); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(name), -1); ++ free(name); ++ ++ name = get_length_str(SOCK_NAME_MAX_LEN); ++ CU_ASSERT_PTR_NOT_NULL(name); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(name), -1); ++ free(name); ++ ++ name = get_length_str(SOCK_NAME_MAX_LEN + 1); ++ CU_ASSERT_PTR_NOT_NULL(name); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(name), -1); ++ free(name); ++} ++ ++static void test_sock_name_ok(void) ++{ ++ char *name = NULL; ++ ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name("name"), 0); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name("n"), 0); ++ ++ name = get_length_str(SOCK_NAME_MAX_LEN - 2); ++ CU_ASSERT_PTR_NOT_NULL(name); ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(name), 0); ++ free(name); ++} ++ ++void *etmemd_rpc_server_start(void *msg) ++{ ++ char *socket_name = (char *)msg; ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(socket_name), -1); ++ etmemd_rpc_server(); ++} ++ ++void *etmemd_rpc_server_start_ok(void *msg) ++{ ++ char *socket_name = (char *)msg; ++ CU_ASSERT_EQUAL(etmemd_parse_sock_name(socket_name), 0); ++ etmemd_rpc_server(); ++} ++ ++static struct mem_proj *alloc_proj(int cmd, char *proj_name, ++ char *file_name, char *sock_name) ++{ ++ struct mem_proj *proj = NULL; ++ proj = (struct mem_proj *)calloc(1, sizeof(struct mem_proj)); ++ CU_ASSERT_PTR_NOT_NULL(proj); ++ ++ proj->cmd = cmd; ++ proj->file_name = file_name; ++ proj->proj_name = proj_name; ++ proj->sock_name = sock_name; ++ ++ return proj; ++} ++ ++static int etmem_socket_client(int cmd, char *proj_name, ++ char *file_name, char *sock_name) ++{ ++ int ret; ++ struct mem_proj *proj = NULL; ++ proj = alloc_proj(cmd, proj_name, file_name, sock_name); ++ ret = etmem_rpc_client(proj); ++ free(proj); ++ if (ret == 0) { ++ return 0; ++ } ++ return -1; ++} ++ ++static void etmem_pro_add_error(void) ++{ ++ char *file_name = NULL; ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, NULL, NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, NULL, "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, NULL, "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, NULL, file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, NULL, "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "", file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "", "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "test", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "test", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "test", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "test", file_name, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "test", "file_name", "sock_name"), -1); ++ free(file_name); ++} ++ ++static void etmem_pro_del_error(void) ++{ ++ char *file_name = NULL; ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, NULL, NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, NULL, "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, NULL, "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, NULL, file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, NULL, "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "", file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "", "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "test", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "test", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "test", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "test", file_name, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "test", "file_name", "sock_name"), -1); ++ free(file_name); ++} ++ ++static void etmem_pro_start_error(void) ++{ ++ char *file_name = NULL; ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, NULL, NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, NULL, "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, NULL, "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, NULL, file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, NULL, "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "", file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "", "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "test", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "test", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "test", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "test", file_name, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "test", "file_name", "sock_name"), -1); ++ free(file_name); ++} ++ ++static void etmem_pro_stop_error(void) ++{ ++ char *file_name = NULL; ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, NULL, NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, NULL, "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, NULL, "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, NULL, file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, NULL, "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "", file_name, ""), -1); ++ free(file_name); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "", "file_name", "sock_name"), -1); ++ ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "test", NULL, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "test", "", ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "test", "file_name", ""), -1); ++ file_name = get_length_str(RPC_SEND_FILE_MAX); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "test", file_name, ""), -1); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "test", "file_name", "sock_name"), -1); ++ free(file_name); ++} ++ ++static void test_socket_client_error(void) ++{ ++ struct mem_proj *proj = NULL; ++ char *project_name = NULL; ++ char *file_name = NULL; ++ char *sock_name = NULL; ++ char *msg = "etmem_error_sock"; ++ ++ pthread_t etmem_socket_test; ++ ++ CU_ASSERT_EQUAL(pthread_create(&etmem_socket_test, NULL, etmemd_rpc_server_start, NULL), EOK); ++ CU_ASSERT_EQUAL(pthread_create(&etmem_socket_test, NULL, ++ etmemd_rpc_server_start_ok, (void *)msg), EOK); ++ usleep(SLEEP_TIME_ONE_T_US); ++ etmem_pro_add_error(); ++ etmem_pro_del_error(); ++ etmem_pro_start_error(); ++ etmem_pro_stop_error(); ++ ++ etmemd_handle_signal(); ++} ++ ++static void test_socket_client_ok(void) ++{ ++ struct mem_proj *proj = NULL; ++ char *project_name = NULL; ++ char *file_name = NULL; ++ char *sock_name = NULL; ++ char *msg = "etmem_ok_sock"; ++ ++ pthread_t etmem_socket_test_ok; ++ ++ CU_ASSERT_EQUAL(pthread_create(&etmem_socket_test_ok, NULL, ++ etmemd_rpc_server_start_ok, (void *)msg), EOK); ++ usleep(SLEEP_TIME_ONE_T_US); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_ADD, "test", ++ "../conf/conf_slide/config_file", msg), 0); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_SHOW, "test", ++ "../conf/conf_slide/config_file", msg), 0); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_START, "test", ++ "../conf/conf_slide/config_file", msg), 0); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_STOP, "test", ++ "../conf/conf_slide/config_file", msg), 0); ++ CU_ASSERT_EQUAL(etmem_socket_client(ETMEM_CMD_DEL, "test", ++ "../conf/conf_slide/config_file", msg), 0); ++ ++ etmemd_handle_signal(); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_socket_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_sock_name_error) == NULL || ++ CU_ADD_TEST(suite, test_sock_name_ok) == NULL || ++ CU_ADD_TEST(suite, test_socket_client_error) == NULL || ++ CU_ADD_TEST(suite, test_socket_client_ok) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_rpc.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +-- +1.8.3.1 + diff --git a/0072-etmem-add-code-of-testcase.patch b/0072-etmem-add-code-of-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc6e60898f55531247844901e0f60b88049a5610 --- /dev/null +++ b/0072-etmem-add-code-of-testcase.patch @@ -0,0 +1,1040 @@ +From 692c7b671b87dd6cc3748426ab22d07b5330ad79 Mon Sep 17 00:00:00 2001 +From: liubo +Date: Mon, 24 Jan 2022 06:42:23 +0800 +Subject: [PATCH 22/33] etmem: add code of testcase + +add code of testcase for etmem task function +add code of testcase for etmem thirdparty function + +Signed-off-by: liubo +--- + .../test/etmem_socket_ops_llt_test/CMakeLists.txt | 2 +- + etmem/test/etmem_task_ops_llt_test/CMakeLists.txt | 26 ++ + .../etmem_task_ops_llt_test/etmem_task_ops_llt.c | 334 ++++++++++++++++ + .../etmem_thirdparty_ops_llt_test/CMakeLists.txt | 30 ++ + .../etmem_thirdparty_ops_llt.c | 425 +++++++++++++++++++++ + .../test/etmem_thirdparty_ops_llt_test/my_engine.c | 156 ++++++++ + 6 files changed, 972 insertions(+), 1 deletion(-) + create mode 100644 etmem/test/etmem_task_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_task_ops_llt_test/etmem_task_ops_llt.c + create mode 100644 etmem/test/etmem_thirdparty_ops_llt_test/CMakeLists.txt + create mode 100644 etmem/test/etmem_thirdparty_ops_llt_test/etmem_thirdparty_ops_llt.c + create mode 100644 etmem/test/etmem_thirdparty_ops_llt_test/my_engine.c + +diff --git a/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt +index 7cc5343..05239a0 100644 +--- a/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt ++++ b/etmem/test/etmem_socket_ops_llt_test/CMakeLists.txt +@@ -10,7 +10,7 @@ + # * See the Mulan PSL v2 for more details. + # * Author: liubo + # * Create: 2021-12-10 +-# * Description: CMakefileList for etmem_log_ops_llt to compile ++# * Description: CMakefileList for etmem_socket_ops_llt to compile + # ******************************************************************************/ + + project(etmem) +diff --git a/etmem/test/etmem_task_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_task_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..ab22dd6 +--- /dev/null ++++ b/etmem/test/etmem_task_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,26 @@ ++s# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-10 ++# * Description: CMakefileList for etmem_task_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_task_ops_llt) ++ ++add_executable(${EXE} etmem_task_ops_llt.c) ++ ++target_link_libraries(${EXE} cunit ${BUILD_DIR}/lib/libetmemd.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_task_ops_llt_test/etmem_task_ops_llt.c b/etmem/test/etmem_task_ops_llt_test/etmem_task_ops_llt.c +new file mode 100644 +index 0000000..7997108 +--- /dev/null ++++ b/etmem/test/etmem_task_ops_llt_test/etmem_task_ops_llt.c +@@ -0,0 +1,334 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-12-10 ++ * Description: This is a source file of the unit test for task functions in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "etmemd_project.h" ++#include "etmemd_task.h" ++#include "etmemd_engine.h" ++#include "etmemd_slide.h" ++#include "etmemd_cslide.h" ++#include "etmemd_rpc.h" ++#include "securec.h" ++ ++#define PID_STR_MAX_LEN 10 ++#define PID_TEST_NUM 100 ++#define PID_PROCESS_MEM 5000 ++#define PID_PROCESS_SLEEP_TIME 60 ++#define WATER_LINT_TEMP 3 ++ ++static void get_task_pids_errinput(char *pid_val, char *pid_type, int exp) ++{ ++ struct task *tk = NULL; ++ ++ tk = (struct task *)calloc(1, sizeof(struct task)); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ tk->type = pid_type; ++ tk->value = pid_val; ++ CU_ASSERT_EQUAL(etmemd_get_task_pids(tk, true), exp); ++ ++ free(tk); ++} ++ ++static void test_get_task_pids_error(void) ++{ ++ get_task_pids_errinput("", "", -1); ++ get_task_pids_errinput("1", "", -1); ++ get_task_pids_errinput("no123", "pid", -1); ++ get_task_pids_errinput("1", "wrong", -1); ++ get_task_pids_errinput("wrong", "name", -1); ++ get_task_pids_errinput("-1", "pid", -1); ++} ++ ++static void add_process(int index) ++{ ++ int pid = fork(); ++ switch (pid) { ++ case 0: /* child process */ ++ { ++ char index_str[PID_PROCESS_MEM] = {0}; ++ if (snprintf_s(index_str, PID_PROCESS_MEM, PID_PROCESS_MEM - 1, "%d", index) <= 0) { ++ printf("get index error.\n"); ++ } ++ prctl(PR_SET_NAME, index_str, NULL, NULL, NULL); ++ sleep(PID_PROCESS_SLEEP_TIME); ++ exit(0); ++ } ++ case -1: /* create process wrong */ ++ { ++ printf("[Worker]: Fork failed!\n"); ++ exit(0); ++ } ++ ++ default: ++ break; ++ } ++} ++ ++static int get_pids(int index) ++{ ++ int pid = getpid(); ++ int i; ++ for (i = 0; i < index; i++) { ++ add_process(i); ++ } ++ return pid; ++} ++ ++static int init_ops(struct task *tk) ++{ ++ tk->eng->ops->fill_eng_params = NULL; ++ tk->eng->ops->clear_eng_params = NULL; ++ tk->eng->ops->fill_task_params = NULL; ++ tk->eng->ops->clear_task_params = NULL; ++ tk->eng->ops->start_task = NULL; ++ tk->eng->ops->stop_task = NULL; ++ tk->eng->ops->alloc_pid_params = NULL; ++ tk->eng->ops->free_pid_params = NULL; ++ tk->eng->ops->eng_mgt_func = NULL; ++} ++ ++static struct task *alloc_task(const char *pid_type, const char *pid_val) ++{ ++ size_t pid_type_len; ++ size_t pid_value_len; ++ struct task *tk = NULL; ++ ++ tk = (struct task *)calloc(1, sizeof(struct task)); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ pid_type_len = strlen(pid_type) + 1; ++ pid_value_len = strlen(pid_val) + 1; ++ ++ tk->type = (char *)calloc(pid_type_len, sizeof(char)); ++ CU_ASSERT_PTR_NOT_NULL(tk->type); ++ if (strncpy_s(tk->type, pid_type_len, pid_type, pid_type_len - 1) != EOK) { ++ free(tk->type); ++ free(tk); ++ return NULL; ++ } ++ ++ tk->value = (char *)calloc(pid_value_len, sizeof(char)); ++ CU_ASSERT_PTR_NOT_NULL(tk->value); ++ if (strncpy_s(tk->value, pid_value_len, pid_val, pid_value_len - 1) != EOK) { ++ free(tk->type); ++ free(tk->value); ++ free(tk); ++ return NULL; ++ } ++ ++ tk->eng = (struct engine *)calloc(1, sizeof(struct engine)); ++ CU_ASSERT_PTR_NOT_NULL(tk->eng); ++ tk->eng->tasks = (void *)tk; ++ ++ tk->eng->ops = (struct engine_ops *)calloc(1, sizeof(struct engine_ops)); ++ CU_ASSERT_PTR_NOT_NULL(tk->eng->ops); ++ init_ops(tk); ++ ++ CU_ASSERT_EQUAL(fill_engine_type_slide(tk->eng, NULL), 0); ++ ++ return tk; ++} ++ ++static void test_get_task_withpid_ok(void) ++{ ++ char pid_val[PID_STR_MAX_LEN] = {0}; ++ char *pid_type = "pid"; ++ struct task *tk = NULL; ++ struct engine *eng = NULL; ++ int pid; ++ ++ pid = get_pids((int)PID_TEST_NUM); ++ if (snprintf_s(pid_val, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%d", pid) <= 0) { ++ printf("snprintf pid fail %d", pid); ++ return; ++ } ++ tk = alloc_task(pid_type, pid_val); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ CU_ASSERT_EQUAL(etmemd_get_task_pids(tk, true), 0); ++ CU_ASSERT_PTR_NOT_NULL(tk->pids); ++ ++ etmemd_free_task_pids(tk); ++ CU_ASSERT_PTR_NULL(tk->pids); ++ ++ etmemd_free_task_struct(&tk); ++ CU_ASSERT_PTR_NULL(tk); ++} ++ ++static void test_get_task_withname_ok(void) ++{ ++ char *pid_val = "systemd"; ++ char *pid_type = "name"; ++ struct task *tk = NULL; ++ ++ tk = alloc_task(pid_type, pid_val); ++ ++ CU_ASSERT_EQUAL(etmemd_get_task_pids(tk, true), 0); ++ CU_ASSERT_PTR_NOT_NULL(tk->pids); ++ ++ etmemd_free_task_pids(tk); ++ CU_ASSERT_PTR_NULL(tk->pids); ++ ++ etmemd_free_task_struct(&tk); ++ CU_ASSERT_PTR_NULL(tk); ++} ++ ++static int get_task_pid(char *type, char *value, struct task *tk) ++{ ++ char pid[PID_STR_MAX_LEN] = {0}; ++ tk->type = type; ++ tk->value = value; ++ return get_pid_from_task_type(tk, pid); ++} ++ ++static void test_get_pid_error(void) ++{ ++ struct task *tk = NULL; ++ ++ tk = (struct task *)calloc(1, sizeof(struct task)); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ CU_ASSERT_EQUAL(get_task_pid("", "", tk), -1); ++ CU_ASSERT_EQUAL(get_task_pid("wrong", "", tk), -1); ++ CU_ASSERT_EQUAL(get_task_pid("", "no123", tk), -1); ++ CU_ASSERT_EQUAL(get_task_pid("pid", "no123", tk), 0); ++ CU_ASSERT_EQUAL(get_task_pid("name", "wrong", tk), -1); ++ free(tk); ++} ++ ++static void test_get_pid_ok(void) ++{ ++ struct task *tk = NULL; ++ ++ tk = (struct task *)calloc(1, sizeof(struct task)); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ CU_ASSERT_EQUAL(get_task_pid("pid", "1", tk), 0); ++ CU_ASSERT_EQUAL(get_task_pid("name", "systemd", tk), 0); ++ free(tk); ++} ++ ++static void test_free_task_pids(void) ++{ ++ struct task *tk = NULL; ++ struct task_pid *tk_pid = NULL; ++ struct slide_params *s_param = NULL; ++ struct engine *eng = NULL; ++ ++ tk = (struct task *)calloc(1, sizeof(struct task)); ++ CU_ASSERT_PTR_NOT_NULL(tk); ++ ++ tk_pid = (struct task_pid *)calloc(1, sizeof(struct task_pid)); ++ CU_ASSERT_PTR_NOT_NULL(tk_pid); ++ tk_pid->pid = 1; ++ ++ s_param = (struct slide_params *)calloc(1, sizeof(struct slide_params)); ++ CU_ASSERT_PTR_NOT_NULL(s_param); ++ s_param->t = WATER_LINT_TEMP; ++ tk_pid->params = s_param; ++ tk_pid->tk = tk; ++ tk->pids = tk_pid; ++ ++ /* add engine */ ++ eng = (struct engine *)calloc(1, sizeof(struct engine)); ++ CU_ASSERT_PTR_NOT_NULL(eng); ++ tk->eng = eng; ++ ++ tk->eng->ops = (struct engine_ops *)calloc(1, sizeof(struct engine_ops)); ++ CU_ASSERT_PTR_NOT_NULL(tk->eng->ops); ++ init_ops(tk); ++ ++ etmemd_free_task_pids(tk); ++ CU_ASSERT_PTR_NULL(tk->pids); ++ free(tk); ++ tk = NULL; ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_task_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_get_task_pids_error) == NULL || ++ CU_ADD_TEST(suite, test_get_task_withpid_ok) == NULL || ++ CU_ADD_TEST(suite, test_get_task_withname_ok) == NULL || ++ CU_ADD_TEST(suite, test_get_pid_error) == NULL || ++ CU_ADD_TEST(suite, test_get_pid_ok) == NULL || ++ CU_ADD_TEST(suite, test_free_task_pids) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_task.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_thirdparty_ops_llt_test/CMakeLists.txt b/etmem/test/etmem_thirdparty_ops_llt_test/CMakeLists.txt +new file mode 100644 +index 0000000..6e82870 +--- /dev/null ++++ b/etmem/test/etmem_thirdparty_ops_llt_test/CMakeLists.txt +@@ -0,0 +1,30 @@ ++# /****************************************************************************** ++# * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++# * etmem is licensed under the Mulan PSL v2. ++# * You can use this software according to the terms and conditions of the Mulan PSL v2. ++# * You may obtain a copy of Mulan PSL v2 at: ++# * http://license.coscl.org.cn/MulanPSL2 ++# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# * PURPOSE. ++# * See the Mulan PSL v2 for more details. ++# * Author: liubo ++# * Create: 2021-12-10 ++# * Description: CMakefileList for etmem_thirdparty_ops_llt to compile ++# ******************************************************************************/ ++ ++project(etmem) ++ ++INCLUDE_DIRECTORIES(../../inc/etmem_inc) ++INCLUDE_DIRECTORIES(../../inc/etmemd_inc) ++INCLUDE_DIRECTORIES(../common) ++INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) ++ ++SET(EXE etmem_thirdparty_ops_llt) ++SET(LIB thirdparty_engine) ++ ++add_library(${LIB} SHARED my_engine.c) ++add_executable(${EXE} etmem_thirdparty_ops_llt.c) ++ ++target_link_libraries(${EXE} ${LIB} ${LIBNULL} cunit ${BUILD_DIR}/lib/libetmemd.so ++ ${BUILD_DIR}/lib/libtest.so pthread dl rt boundscheck numa ${GLIB2_LIBRARIES}) +diff --git a/etmem/test/etmem_thirdparty_ops_llt_test/etmem_thirdparty_ops_llt.c b/etmem/test/etmem_thirdparty_ops_llt_test/etmem_thirdparty_ops_llt.c +new file mode 100644 +index 0000000..d7e7ae4 +--- /dev/null ++++ b/etmem/test/etmem_thirdparty_ops_llt_test/etmem_thirdparty_ops_llt.c +@@ -0,0 +1,425 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-12-10 ++ * Description: This is a source file of the unit test for thirdparty functions in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "test_common.h" ++#include "etmemd_thirdparty_export.h" ++#include "etmemd_project.h" ++ ++#define CONFIG_ENGINE_NAME "eng_name=%s\n" ++#define CONFIG_LIBNAME "libname=%s\n" ++#define CONFIG_OPS_NAME "ops_name=%s\n" ++#define CONFIG_ENGINE_PRIVATE_KEY "engine_private_key=%s\n" ++ ++#define CONFIG_TASK_PRIVATE_KEY "task_private_key=%s\n" ++ ++struct thirdparty_eng_param { ++ struct eng_test_param eng_param; ++ const char *engine_name; ++ const char *libname; ++ const char *ops_name; ++ const char *engine_private_key; ++}; ++ ++struct thirdparty_task_param { ++ struct task_test_param task_param; ++ const char *task_private_key; ++}; ++ ++static struct proj_test_param g_proj_param; ++ ++static void init_thirdparty_eng(struct thirdparty_eng_param *param, ++ const char *libname, const char *ops_name) ++{ ++ param->eng_param.name = "thirdparty"; ++ param->eng_param.proj = DEFAULT_PROJ; ++ param->eng_param.file_name = TMP_TASK_CONFIG; ++ param->engine_name = "my_engine"; ++ param->libname = libname; ++ param->ops_name = ops_name; ++ param->engine_private_key = "1024"; ++} ++ ++static void add_thirdparty_eng(struct thirdparty_eng_param *param) ++{ ++ FILE *file = NULL; ++ const char *file_name = param->eng_param.file_name; ++ ++ file = fopen(file_name, "a+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_ENGINE_NAME, param->engine_name), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_LIBNAME, param->libname), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_OPS_NAME, param->ops_name), -1); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_ENGINE_PRIVATE_KEY, param->engine_private_key), -1); ++ fclose(file); ++} ++ ++static GKeyFile *construct_thirdparty_eng_config(struct thirdparty_eng_param *param) ++{ ++ struct eng_test_param *eng_param = ¶m->eng_param; ++ ++ construct_eng_file(eng_param); ++ add_thirdparty_eng(param); ++ ++ return load_config(eng_param->file_name); ++} ++ ++static void destroy_thirdparty_eng_config(GKeyFile *config) ++{ ++ unload_config(config); ++} ++ ++static void init_thirdparty_task(struct thirdparty_task_param *param) ++{ ++ init_task_param(¶m->task_param, "my_engine"); ++ param->task_private_key = "2048"; ++} ++ ++static void add_thirdparty_task(struct thirdparty_task_param *param) ++{ ++ FILE *file = NULL; ++ const char *file_name = param->task_param.file_name; ++ ++ file = fopen(file_name, "a+"); ++ CU_ASSERT_PTR_NOT_NULL(file); ++ CU_ASSERT_NOT_EQUAL(fprintf(file, CONFIG_TASK_PRIVATE_KEY, param->task_private_key), -1); ++ fclose(file); ++} ++ ++static GKeyFile *construct_thirdparty_task_config(struct thirdparty_task_param *param) ++{ ++ struct task_test_param *task_param = ¶m->task_param; ++ ++ construct_task_file(task_param); ++ add_thirdparty_task(param); ++ ++ return load_config(task_param->file_name); ++} ++ ++static void destroy_thirdparty_task_config(GKeyFile *config) ++{ ++ unload_config(config); ++} ++ ++static void test_init(void) ++{ ++ init_proj_param(&g_proj_param); ++ do_add_proj_test(&g_proj_param); ++} ++ ++static void test_fini(void) ++{ ++ do_rm_proj_test(&g_proj_param); ++} ++ ++static void test_etmem_mgt_engine_error(void) ++{ ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(NULL, NULL, NULL, DEFAULT_TASK, 0), OPT_INVAL); ++} ++ ++void test_etmem_user_engine_0001(void) ++{ ++ struct thirdparty_eng_param thirdparty_engine_param; ++ struct thirdparty_task_param thirdparty_task_param; ++ GKeyFile *eng_config = NULL; ++ GKeyFile *task_config = NULL; ++ ++ test_init(); ++ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "my_engine_ops"); ++ init_thirdparty_task(&thirdparty_task_param); ++ ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ ++ task_config = construct_thirdparty_task_config(&thirdparty_task_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_SUCCESS); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(DEFAULT_PROJ, "my_engine", ++ "my_cmd", DEFAULT_TASK, 0), OPT_SUCCESS); ++ ++ /* test param NULL */ ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(NULL, NULL, ++ NULL, DEFAULT_TASK, 0), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(DEFAULT_PROJ, "no_exist_engine", ++ "my_cmd", DEFAULT_TASK, 0), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(DEFAULT_PROJ, "my_engine", ++ "my_cmd", "no_exist_task", 0), OPT_SUCCESS); ++ ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ ++ /* test for project not start */ ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(DEFAULT_PROJ, "my_engine", ++ "my_cmd", DEFAULT_TASK, 0), OPT_INVAL); ++ ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(eng_config), OPT_SUCCESS); ++ ++ destroy_thirdparty_task_config(task_config); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "start_error_ops"); ++ init_thirdparty_task(&thirdparty_task_param); ++ ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ ++ task_config = construct_thirdparty_task_config(&thirdparty_task_param); ++ /* start task fail when start projecct */ ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_INTER_ERR); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(task_config), OPT_SUCCESS); ++ ++ /* add task fail if project is already start */ ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_INTER_ERR); ++ ++ destroy_thirdparty_task_config(task_config); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ test_fini(); ++} ++ ++static void test_etmem_user_engine_null(void) ++{ ++ struct thirdparty_eng_param thirdparty_engine_param; ++ struct thirdparty_task_param thirdparty_task_param; ++ GKeyFile *eng_config = NULL; ++ GKeyFile *task_config = NULL; ++ ++ test_init(); ++ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "start_not_null_ops"); ++ init_thirdparty_task(&thirdparty_task_param); ++ ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ task_config = construct_thirdparty_task_config(&thirdparty_task_param); ++ ++ /* only start task is not null to cover null mgt and stop */ ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_mgt_engine(DEFAULT_PROJ, "my_engine", ++ "my_cmd", DEFAULT_TASK, 0), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(eng_config), OPT_SUCCESS); ++ ++ destroy_thirdparty_task_config(task_config); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ test_fini(); ++ ++ test_init(); ++ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "start_null_ops"); ++ init_thirdparty_task(&thirdparty_task_param); ++ ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ task_config = construct_thirdparty_task_config(&thirdparty_task_param); ++ ++ /* start task manually */ ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_INTER_ERR); ++ CU_ASSERT_EQUAL(etmemd_project_remove_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(eng_config), OPT_SUCCESS); ++ ++ /* start task auto (project is already start when add a task) */ ++ CU_ASSERT_EQUAL(etmemd_migrate_start(DEFAULT_PROJ), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_add_task(task_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(eng_config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_migrate_stop(DEFAULT_PROJ), OPT_SUCCESS); ++ ++ destroy_thirdparty_task_config(task_config); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ test_fini(); ++} ++ ++static void test_etmem_invalid_config(void) ++{ ++ struct thirdparty_eng_param thirdparty_engine_param; ++ GKeyFile *eng_config = NULL; ++ ++ test_init(); ++ ++ /* test invalid so */ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/invalid.so", "my_engine_ops"); ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ /* test invalid engine name */ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "my_engine_ops"); ++ thirdparty_engine_param.engine_name = "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ /* test invalid ops */ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "no_exist_ops"); ++ eng_config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_NOT_EQUAL(etmemd_project_add_engine(eng_config), OPT_SUCCESS); ++ destroy_thirdparty_eng_config(eng_config); ++ ++ test_fini(); ++} ++ ++void test_etmem_user_engine_0002(void) ++{ ++ test_etmem_user_engine_null(); ++} ++ ++/* add correct thirdparty config */ ++void test_etmem_add_thirdparty_0001(void) ++{ ++ struct thirdparty_eng_param thirdparty_engine_param; ++ GKeyFile *config = NULL; ++ ++ test_init(); ++ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "my_engine_ops"); ++ config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_SUCCESS); ++ destroy_thirdparty_eng_config(config); ++ ++ test_fini(); ++} ++ ++/* add wrong thirdparty config */ ++void test_etmem_add_thirdparty_0002(void) ++{ ++ test_etmem_invalid_config(); ++} ++ ++/* del correct thirdparty config */ ++void test_etmem_del_thirdparty_0001(void) ++{ ++ struct thirdparty_eng_param thirdparty_engine_param; ++ GKeyFile *config = NULL; ++ ++ test_init(); ++ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "my_engine_ops"); ++ config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_EQUAL(etmemd_project_add_engine(config), OPT_SUCCESS); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_SUCCESS); ++ destroy_thirdparty_eng_config(config); ++ ++ test_fini(); ++} ++ ++/* del wrong thirdparty config */ ++void test_etmem_del_thirdparty_0002(void) ++{ ++ struct thirdparty_eng_param thirdparty_engine_param; ++ GKeyFile *config = NULL; ++ ++ test_init(); ++ ++ /* del no exist engine */ ++ init_thirdparty_eng(&thirdparty_engine_param, "./lib/libthirdparty_engine.so", "my_engine_ops"); ++ config = construct_thirdparty_eng_config(&thirdparty_engine_param); ++ CU_ASSERT_EQUAL(etmemd_project_remove_engine(config), OPT_ENG_NOEXIST); ++ destroy_thirdparty_eng_config(config); ++ ++ test_fini(); ++} ++ ++void do_rm_proj_test(struct proj_test_param *param) ++{ ++ GKeyFile *config = NULL; ++ ++ config = load_config(param->file_name); ++ CU_ASSERT_EQUAL(etmemd_project_remove(config), param->expt); ++ unload_config(config); ++} ++ ++typedef enum { ++ CUNIT_SCREEN = 0, ++ CUNIT_XMLFILE, ++ CUNIT_CONSOLE ++} cu_run_mode; ++ ++int main(int argc, const char **argv) ++{ ++ CU_pSuite suite; ++ CU_pTest pTest; ++ unsigned int num_failures; ++ cu_run_mode cunit_mode = CUNIT_SCREEN; ++ int error_num; ++ ++ if (argc > 1) { ++ cunit_mode = atoi(argv[1]); ++ } ++ ++ if (CU_initialize_registry() != CUE_SUCCESS) { ++ return -CU_get_error(); ++ } ++ ++ suite = CU_add_suite("etmem_thirdparty_ops", NULL, NULL); ++ if (suite == NULL) { ++ goto ERROR; ++ } ++ ++ if (CU_ADD_TEST(suite, test_etmem_user_engine_0001) == NULL || ++ CU_ADD_TEST(suite, test_etmem_user_engine_0002) == NULL || ++ CU_ADD_TEST(suite, test_etmem_add_thirdparty_0001) == NULL || ++ CU_ADD_TEST(suite, test_etmem_add_thirdparty_0002) == NULL || ++ CU_ADD_TEST(suite, test_etmem_del_thirdparty_0001) == NULL || ++ CU_ADD_TEST(suite, test_etmem_del_thirdparty_0002) == NULL) { ++ printf("CU_ADD_TEST fail. \n"); ++ goto ERROR; ++ } ++ ++ switch (cunit_mode) { ++ case CUNIT_SCREEN: ++ CU_basic_set_mode(CU_BRM_VERBOSE); ++ CU_basic_run_tests(); ++ break; ++ case CUNIT_XMLFILE: ++ CU_set_output_filename("etmemd_thirdparty.c"); ++ CU_automated_run_tests(); ++ break; ++ case CUNIT_CONSOLE: ++ CU_console_run_tests(); ++ break; ++ default: ++ printf("not support cunit mode, only support: " ++ "0 for CUNIT_SCREEN, 1 for CUNIT_XMLFILE, 2 for CUNIT_CONSOLE\n"); ++ goto ERROR; ++ } ++ ++ num_failures = CU_get_number_of_failures(); ++ CU_cleanup_registry(); ++ return num_failures; ++ ++ERROR: ++ error_num = CU_get_error(); ++ CU_cleanup_registry(); ++ return -error_num; ++} +diff --git a/etmem/test/etmem_thirdparty_ops_llt_test/my_engine.c b/etmem/test/etmem_thirdparty_ops_llt_test/my_engine.c +new file mode 100644 +index 0000000..bd2a3bc +--- /dev/null ++++ b/etmem/test/etmem_thirdparty_ops_llt_test/my_engine.c +@@ -0,0 +1,156 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. ++ * etmem is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: liubo ++ * Create: 2021-12-10 ++ * Description: This is a source file of the unit test for task functions in etmem. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++ ++#include "etmemd_thirdparty_export.h" ++ ++char *get_private_value(GKeyFile *config, char *group, char *key) ++{ ++ if (g_key_file_has_key(config, group, key, NULL) == FALSE) { ++ return NULL; ++ } ++ ++ return g_key_file_get_string(config, group, key, NULL); ++} ++ ++char *get_params_str(void *str) ++{ ++ return str == NULL ? "NULL" : (char *)str; ++} ++ ++int fill_eng_params(GKeyFile *config, struct engine *eng) ++{ ++ /* engine_private_key is user defined key name in engine group in config file */ ++ eng->params = get_private_value(config, "engine", "engine_private_key"); ++ if (strcmp(eng->params, "1024") != 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void clear_eng_params(struct engine *eng) ++{ ++ if (eng->params != NULL) { ++ free(eng->params); ++ eng->params = NULL; ++ } ++} ++ ++int fill_task_params(GKeyFile *config, struct task *task) ++{ ++ /* task_private_key is user defined key name in task group in config file */ ++ task->params = get_private_value(config, "task", "task_private_key"); ++ if (strcmp(task->params, "2048") != 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void clear_task_params(struct task *task) ++{ ++ if (task->params != NULL) { ++ free(task->params); ++ task->params = NULL; ++ } ++} ++ ++int start_task(struct engine *eng, struct task *task) ++{ ++ return 0; ++} ++ ++static int my_start_task(struct engine *eng, struct task *tk) ++{ ++ return 0; ++} ++ ++int error_start_task(struct engine *eng, struct task *task) ++{ ++ return -1; ++} ++ ++void stop_task(struct engine *eng, struct task *task) ++{ ++} ++ ++int alloc_pid_params(struct engine *eng, struct task_pid **tk_pid) ++{ ++ return 0; ++} ++ ++void free_pid_params(struct engine *eng, struct task_pid **tk_pid) ++{ ++} ++ ++int eng_mgt_func(struct engine *eng, struct task *task, char *cmd, int fd) ++{ ++ char *msg = "msg to client\n"; ++ ++ write(fd, msg, strlen(msg)); ++ return 0; ++} ++ ++struct engine_ops my_engine_ops = { ++ .fill_eng_params = fill_eng_params, ++ .clear_eng_params = clear_eng_params, ++ .fill_task_params = fill_task_params, ++ .clear_task_params = clear_task_params, ++ .start_task = start_task, ++ .stop_task = stop_task, ++ .alloc_pid_params = alloc_pid_params, ++ .free_pid_params = free_pid_params, ++ .eng_mgt_func = eng_mgt_func, ++}; ++ ++struct engine_ops start_error_ops = { ++ .fill_eng_params = fill_eng_params, ++ .clear_eng_params = clear_eng_params, ++ .fill_task_params = fill_task_params, ++ .clear_task_params = clear_task_params, ++ .start_task = error_start_task, ++ .stop_task = stop_task, ++ .alloc_pid_params = alloc_pid_params, ++ .free_pid_params = free_pid_params, ++ .eng_mgt_func = eng_mgt_func, ++}; ++ ++struct engine_ops start_not_null_ops = { ++ .fill_eng_params = NULL, ++ .clear_eng_params = NULL, ++ .fill_task_params = NULL, ++ .clear_task_params = NULL, ++ .start_task = my_start_task, ++ .stop_task = NULL, ++ .alloc_pid_params = NULL, ++ .free_pid_params = NULL, ++ .eng_mgt_func = NULL, ++}; ++ ++struct engine_ops start_null_ops = { ++ .fill_eng_params = NULL, ++ .clear_eng_params = NULL, ++ .fill_task_params = NULL, ++ .clear_task_params = NULL, ++ .start_task = NULL, ++ .stop_task = NULL, ++ .alloc_pid_params = NULL, ++ .free_pid_params = NULL, ++ .eng_mgt_func = NULL, ++}; +-- +1.8.3.1 + diff --git a/0073-etmem-add-testcode-script.patch b/0073-etmem-add-testcode-script.patch new file mode 100644 index 0000000000000000000000000000000000000000..1369057ddde46a7878a1caa4a95dbccd27ac94de --- /dev/null +++ b/0073-etmem-add-testcode-script.patch @@ -0,0 +1,308 @@ +From 2d15999e02c34c2580bb8744a143806e4391338e Mon Sep 17 00:00:00 2001 +From: liubo +Date: Mon, 24 Jan 2022 07:52:02 +0800 +Subject: [PATCH 23/33] etmem: add testcode script + +add test.sh, the testcode compile and run script, for etmem. + +Signed-off-by: liubo +--- + etmem/test/test.sh | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 286 insertions(+) + create mode 100644 etmem/test/test.sh + +diff --git a/etmem/test/test.sh b/etmem/test/test.sh +new file mode 100644 +index 0000000..55a8cd9 +--- /dev/null ++++ b/etmem/test/test.sh +@@ -0,0 +1,286 @@ ++#!/bin/bash ++ ++run_test_exit_value=0 ++usage() ++{ ++ echo "Usage: sh test.sh [OPTIONS]" ++ echo "Use test.sh to control test operation" ++ echo ++ echo "Misc:" ++ echo " -h, --help Print this help, then exit" ++ echo ++ echo "Compile Options:" ++ echo " -m, --cmake