From f369ce160545c4328c9b5a1dd7a224897da57ed9 Mon Sep 17 00:00:00 2001 From: queyanwen Date: Sat, 2 Jul 2022 18:05:03 +0800 Subject: [PATCH] Basic structure. --- .gitignore | 5 + CMakeLists.txt | 7 + LICENSE | 127 +++++ build.sh | 42 ++ clean.sh | 13 + common/inc/pwrbuffer.h | 77 ++++ common/inc/pwrdata.h | 24 + common/inc/pwrerr.h | 29 ++ common/inc/pwrmsg.h | 94 ++++ common/src/pwrbuffer.c | 257 +++++++++++ common/src/pwrmsg.c | 147 ++++++ install.sh | 5 + pwrapic/CMakeLists.txt | 6 + pwrapic/inc/powerapi.h | 41 ++ pwrapic/inc/pwrcpu.h | 23 + pwrapic/inc/pwrlog.h | 37 ++ pwrapic/inc/sockclient.h | 23 + pwrapic/src/CMakeLists.txt | 32 ++ pwrapic/src/powerapi.c | 73 +++ pwrapic/src/pwrcpu.c | 67 +++ pwrapic/src/sockclient.c | 316 +++++++++++++ pwrapic/test/CMakeLists.txt | 29 ++ pwrapic/test/demo_main.c | 91 ++++ pwrapis/conf/pwrapis_config.ini | 17 + pwrapis/inc/common.h | 271 +++++++++++ pwrapis/inc/config.h | 57 +++ pwrapis/inc/cpuservice.h | 20 + pwrapis/inc/log.h | 37 ++ pwrapis/inc/pwrclient.h | 30 ++ pwrapis/inc/server.h | 31 ++ pwrapis/inc/utils.h | 218 +++++++++ pwrapis/pwrapis.service | 11 + pwrapis/src/CMakeLists.txt | 36 ++ pwrapis/src/config.c | 121 +++++ pwrapis/src/cpuservice.c | 48 ++ pwrapis/src/log.c | 221 +++++++++ pwrapis/src/main_frame.c | 100 ++++ pwrapis/src/pwrclient.c | 116 +++++ pwrapis/src/server.c | 399 ++++++++++++++++ pwrapis/src/utils.c | 791 ++++++++++++++++++++++++++++++++ uninstall.sh | 5 + 41 files changed, 4094 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 build.sh create mode 100644 clean.sh create mode 100644 common/inc/pwrbuffer.h create mode 100644 common/inc/pwrdata.h create mode 100644 common/inc/pwrerr.h create mode 100644 common/inc/pwrmsg.h create mode 100644 common/src/pwrbuffer.c create mode 100644 common/src/pwrmsg.c create mode 100644 install.sh create mode 100644 pwrapic/CMakeLists.txt create mode 100644 pwrapic/inc/powerapi.h create mode 100644 pwrapic/inc/pwrcpu.h create mode 100644 pwrapic/inc/pwrlog.h create mode 100644 pwrapic/inc/sockclient.h create mode 100644 pwrapic/src/CMakeLists.txt create mode 100644 pwrapic/src/powerapi.c create mode 100644 pwrapic/src/pwrcpu.c create mode 100644 pwrapic/src/sockclient.c create mode 100644 pwrapic/test/CMakeLists.txt create mode 100644 pwrapic/test/demo_main.c create mode 100644 pwrapis/conf/pwrapis_config.ini create mode 100644 pwrapis/inc/common.h create mode 100644 pwrapis/inc/config.h create mode 100644 pwrapis/inc/cpuservice.h create mode 100644 pwrapis/inc/log.h create mode 100644 pwrapis/inc/pwrclient.h create mode 100644 pwrapis/inc/server.h create mode 100644 pwrapis/inc/utils.h create mode 100644 pwrapis/pwrapis.service create mode 100644 pwrapis/src/CMakeLists.txt create mode 100644 pwrapis/src/config.c create mode 100644 pwrapis/src/cpuservice.c create mode 100644 pwrapis/src/log.c create mode 100644 pwrapis/src/main_frame.c create mode 100644 pwrapis/src/pwrclient.c create mode 100644 pwrapis/src/server.c create mode 100644 pwrapis/src/utils.c create mode 100644 uninstall.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8660c18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.vscode +install +build +release +debug \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d4b9f04 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required (VERSION 3.19) +project (powerapi_entrance C) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_subdirectory(pwrapic/src) +add_subdirectory(pwrapic/test) +add_subdirectory(pwrapis/src) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ee58399 --- /dev/null +++ b/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. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..c9c0539 --- /dev/null +++ b/build.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +PWRAPIC="client" +PWRAPIS="server" + +mkdir build +cd build +cmake .. + +if [[ "$1" == "$PWRAPIC" ]] +then + make pwrapi + make pwrapic_demo +elif [[ "$1" == "$PWRAPIS" ]] +then + make pwrapis +else + make all +fi + +cd .. +rm -rf release +mkdir release +mkdir ./release/pwrapic +mkdir ./release/pwrapic/lib +mkdir ./release/pwrapic/inc +cp ./build/pwrapic/src/libpwrapi.so ./release/pwrapic/lib/ +cp ./pwrapic/inc/powerapi.h ./release/pwrapic/inc/ +cp ./common/inc/pwrdata.h ./release/pwrapic/inc/ +cp ./common/inc/pwrerr.h ./release/pwrapic/inc/ + +mkdir ./release/pwrapi_demo +cp ./build/pwrapic/test/pwrapic_demo ./release/pwrapi_demo/ +cp -r ./release/pwrapic ./release/pwrapi_demo/ + +mkdir ./release/pwrapis +cp ./build/pwrapis/src/pwrapis ./release/pwrapis/ +cp -r ./pwrapis/conf ./release/pwrapis/ + +#make clean +#cd .. +#rm -rf build \ No newline at end of file diff --git a/clean.sh b/clean.sh new file mode 100644 index 0000000..65b9b88 --- /dev/null +++ b/clean.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +find . -name "cmake_install.cmake" |xargs rm -rf +find . -name "CMakeCache.txt" |xargs rm -rf +find . -name "compile_commands.json" |xargs rm -rf +find . -name "Makefile" |xargs rm -rf +find . -name "CMakeFiles" |xargs rm -rf +find . -name "install_manifest.txt" |xargs rm -rf + +rm -rf ./pwrapis/build +rm -rf ./pwrapic/build +rm -rf build +rm -rf release \ No newline at end of file diff --git a/common/inc/pwrbuffer.h b/common/inc/pwrbuffer.h new file mode 100644 index 0000000..d0a51c2 --- /dev/null +++ b/common/inc/pwrbuffer.h @@ -0,0 +1,77 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Provide buffer struct and operations + * **************************************************************************** */ +#ifndef __POWERAPI_UTILS_H__ +#define __POWERAPI_UTILS_H__ +#include "pwrmsg.h" +#include +#include + +#define PWR_BUFFER_SIZE 64 +// Ring Queue, FIFO +typedef struct PwrMsgBuffer { + int head; + int tail; + pthread_mutex_t mutex; + PwrMsg *msgList[PWR_BUFFER_SIZE]; +} PwrMsgBuffer; + +// List +struct __ResultWaitingMsgNode { + pthread_mutex_t waitMutex; + pthread_cond_t waitCond; + struct __ResultWaitingMsgNode *next; + struct __ResultWaitingMsgNode *prev; + PwrMsg *reqMsg; + PwrMsg *rspMsg; +}; +typedef struct __ResultWaitingMsgNode ResultWaitingMsgNode; + +typedef struct ResultWaitingMsgList { + ResultWaitingMsgNode *head; + ResultWaitingMsgNode *tail; + pthread_mutex_t mutex; +} ResultWaitingMsgList; + +void InitPwrMsgBuffer(PwrMsgBuffer *smb); +void ResetPwrMsgBuffer(PwrMsgBuffer *smb); +int AddToBufferTail(PwrMsgBuffer *smb, PwrMsg *newMsg); +PwrMsg *PopFromBufferHead(PwrMsgBuffer *smb); +static inline int IsEmptyBuffer(const PwrMsgBuffer *smb) +{ + if (!smb) { + return 1; + } + return smb->head == smb->tail; +} +static inline int IsFullBuffer(const PwrMsgBuffer *smb) +{ + if (!smb) { + return 0; + } + int t = (smb->head + 1) % PWR_BUFFER_SIZE; + return t == smb->head; +} + +ResultWaitingMsgNode *CreateResultWaitingMsgNode(); +void ReleaseResultWaitingMsgNode(ResultWaitingMsgNode *node); +void InitResultWaitingList(ResultWaitingMsgList *rwm); +void ResetResultWaitingList(ResultWaitingMsgList *rwm); +void AddToWaitingListTail(ResultWaitingMsgList *rwm, ResultWaitingMsgNode *newNode); +ResultWaitingMsgNode *FindAndMoveWaitingMsg(ResultWaitingMsgList *rwm, uint32_t seqId); +void MoveOutWaitingMsg(ResultWaitingMsgList *rwm, ResultWaitingMsgNode *node); +int WaitingForResponse(const ResultWaitingMsgNode *node); +int DoRspToWaitingMsg(const ResultWaitingMsgNode *node); + +#endif diff --git a/common/inc/pwrdata.h b/common/inc/pwrdata.h new file mode 100644 index 0000000..88a87ab --- /dev/null +++ b/common/inc/pwrdata.h @@ -0,0 +1,24 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: The structures definition of powerAPI. + * **************************************************************************** */ +#ifndef __POWERAPI_DATA_H__ +#define __POWERAPI_DATA_H__ + + +typedef struct CPUUsage { + // todo complete CPUUsage definition + int usage; +} CPUUsage; + +#endif diff --git a/common/inc/pwrerr.h b/common/inc/pwrerr.h new file mode 100644 index 0000000..1c30aa4 --- /dev/null +++ b/common/inc/pwrerr.h @@ -0,0 +1,29 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: The return code difinition of PowerAPI + * **************************************************************************** */ +#ifndef __POWERAPI_ERR_H__ +#define __POWERAPI_ERR_H__ + +enum RtnCode { + SUCCESS = 0, + ERR_COMMON = 1, + ERR_TIMEOUT, + ERR_SYS_EXCEPTION, + ERR_NULL_POINTER, + ERR_INVALIDE_PARAM, + ERR_NOT_REGISTED = 100, + ERR_OVER_MAX_CONNECTION, + ERR_DISCONNECTED = 300, +}; +#endif diff --git a/common/inc/pwrmsg.h b/common/inc/pwrmsg.h new file mode 100644 index 0000000..c2adc7b --- /dev/null +++ b/common/inc/pwrmsg.h @@ -0,0 +1,94 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Message struct and operations definition. These messages used for communication between + * PowerAPI.so and PowerAPI service. + * **************************************************************************** */ +#ifndef __POWERAPI_PROTOCOL_H__ +#define __POWERAPI_PROTOCOL_H__ + +#include "pwrerr.h" +#include +#include +#include +#include + +#define MAJOR_VERSION 1 +#define MINOR_VERSION 0 +#define MAX_DATA_SIZE 4096 + +typedef struct MsgHead { + uint8_t majorVer; + uint8_t minorVer; + uint16_t optType; + uint8_t dataFormat; + uint8_t msgType; + uint16_t rspCode; + uint32_t seqId; + uint32_t taskNo; + uint32_t crcMagic; + uint32_t dataLen; + uint32_t sysId; // 消息源头的系统标识,IPC场景使用PID + char reserved[4]; +} MsgHead; + +typedef struct PwrMsg { + MsgHead head; + char *data; +} PwrMsg; + +enum OperationType { + GET_CPU_USAGE = 0, + GET_CPU_CACHE_MISS, + GET_CPU_TOP, + GET_DISK_IO_RATE = 30, + // todo +}; +enum DataFormat { + FMT_BIN = 0, +}; +enum MsgType { + MT_REQ = 0, // Request message + MT_RSP, // Response message + MT_EVT, // event notification + MT_MDT // metadata +}; + +static inline void ReleasePwrMsg(PwrMsg **msg) +{ + if (msg == NULL || *msg == NULL) { + return; + } + free((*msg)->data); + (*msg)->data = NULL; + free(*msg); + *msg = NULL; +} + +int GenerateReqMsg(PwrMsg *msg, enum OperationType optType, uint32_t dataLen, uint32_t taskNo, char *data); +PwrMsg *ClonePwrMsg(PwrMsg *msg); +int InitMsgFactory(); +int GenerateRspMsg(PwrMsg *req, PwrMsg *rsp, int rspCode, char *data, int dataLen); + +#define TRUE 1 +#define FALSE 0 +typedef struct ThreadInfo { + pthread_t tid; + int keepRunning; + int created; +} ThreadInfo; + +void InitThreadInfo(ThreadInfo *threadInfo); +int CreateThread(ThreadInfo *threadInfo, void *(*thread_proc)(void *)); +void FiniThreadInfo(ThreadInfo *threadInfo); + +#endif diff --git a/common/src/pwrbuffer.c b/common/src/pwrbuffer.c new file mode 100644 index 0000000..cf77c71 --- /dev/null +++ b/common/src/pwrbuffer.c @@ -0,0 +1,257 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Provide buffer struct and operations + * **************************************************************************** */ +#include "pwrbuffer.h" +#include +#include +#include + +#define WAITING_RESULT_TIME_OUT 1 // second +// queue private +static void DeleteFromHead(PwrMsgBuffer *smb) +{ + if (!IsEmptyBuffer(smb)) { + int t = (smb->head + 1) % PWR_BUFFER_SIZE; + ReleasePwrMsg(&(smb->msgList[t])); + smb->head = t; + } +} + +// queue public================================================================= +void InitPwrMsgBuffer(PwrMsgBuffer *smb) +{ + if (!smb) { + return; + } + bzero(smb, sizeof(PwrMsgBuffer)); + pthread_mutex_init((pthread_mutex_t *)&(smb->mutex), NULL); +} + +void ResetPwrMsgBuffer(PwrMsgBuffer *smb) +{ + if (!smb) { + return; + } + pthread_mutex_lock((pthread_mutex_t *)&(smb->mutex)); + for (int i = smb->head; i != smb->tail;) { + ReleasePwrMsg(&smb->msgList[i]); + i = (i + 1) % PWR_BUFFER_SIZE; + } + pthread_mutex_unlock((pthread_mutex_t *)&(smb->mutex)); + pthread_mutex_destroy((pthread_mutex_t *)&(smb->mutex)); +} + +int AddToBufferTail(PwrMsgBuffer *smb, PwrMsg *newMsg) +{ + if (!smb || !newMsg) { + return ERR_NULL_POINTER; + } + pthread_mutex_lock((pthread_mutex_t *)&(smb->mutex)); + int t = (smb->tail + 1) % PWR_BUFFER_SIZE; + if (t == smb->head) { // the queue is full + DeleteFromHead(smb); + } + smb->msgList[t] = newMsg; + smb->tail = t; + pthread_mutex_unlock((pthread_mutex_t *)&(smb->mutex)); + return 0; +} + +PwrMsg *PopFromBufferHead(PwrMsgBuffer *smb) +{ + if (!smb) { + return NULL; + } + PwrMsg *p = NULL; + pthread_mutex_lock((pthread_mutex_t *)&(smb->mutex)); + if (!IsEmptyBuffer(smb)) { + int t = (smb->head + 1) % PWR_BUFFER_SIZE; + p = smb->msgList[t]; + smb->msgList[t] = NULL; + smb->head = t; + } + pthread_mutex_unlock((pthread_mutex_t *)&(smb->mutex)); + return p; +} + +// list private====================================================================== +static ResultWaitingMsgNode *MoveFromList(ResultWaitingMsgList *rwm, ResultWaitingMsgNode *node) +{ + if (!rwm || !node) { + return NULL; + } + if (node == rwm->head && rwm->head == rwm->tail) { + rwm->head = NULL; + rwm->tail = NULL; + } else if (node == rwm->head) { + rwm->head = node->next; + rwm->head->prev = NULL; + } else if (node == rwm->tail) { + rwm->tail = node->prev; + rwm->tail->next = NULL; + } else { + node->prev->next = node->next; + node->next->prev = node->prev; + } + node->next = NULL; + node->prev = NULL; + return node; +} + + +// list public======================================================================= + +ResultWaitingMsgNode *CreateResultWaitingMsgNode() +{ + ResultWaitingMsgNode *node = (ResultWaitingMsgNode *)malloc(sizeof(ResultWaitingMsgNode)); + if (!node) { + return NULL; + } + bzero(node, sizeof(ResultWaitingMsgNode)); + pthread_mutex_init((pthread_mutex_t *)&(node->waitMutex), NULL); + pthread_cond_init((pthread_cond_t *)&(node->waitCond), NULL); + return node; +} + +void ReleaseResultWaitingMsgNode(ResultWaitingMsgNode *node) +{ + if (!node) { + return; + } + pthread_mutex_lock((pthread_mutex_t *)&(node->waitMutex)); + ReleasePwrMsg(&node->reqMsg); + ReleasePwrMsg(&node->rspMsg); + node->next = NULL; + node->prev = NULL; + pthread_cond_destroy((pthread_cond_t *)&(node->waitCond)); + pthread_mutex_unlock((pthread_mutex_t *)&(node->waitMutex)); + pthread_mutex_destroy((pthread_mutex_t *)&(node->waitMutex)); +} + +void InitResultWaitingList(ResultWaitingMsgList *rwm) +{ + if (!rwm) { + return; + } + rwm->head = NULL; + rwm->tail = NULL; + pthread_mutex_init((pthread_mutex_t *)&(rwm->mutex), NULL); +} + +void ResetResultWaitingList(ResultWaitingMsgList *rwm) +{ + if (!rwm) { + return; + } + pthread_mutex_lock((pthread_mutex_t *)&(rwm->mutex)); + ResultWaitingMsgNode *pc = rwm->head; + ResultWaitingMsgNode *pn = NULL; + while (pc != NULL) { + pn = pc->next; + ReleaseResultWaitingMsgNode(pc); + pc = pn; + } + rwm->head = NULL; + rwm->tail = NULL; + pthread_mutex_unlock((pthread_mutex_t *)&(rwm->mutex)); + pthread_mutex_destroy((pthread_mutex_t *)&(rwm->mutex)); +} + +void AddToWaitingListTail(ResultWaitingMsgList *rwm, ResultWaitingMsgNode *newNode) +{ + if (!rwm || !newNode) { + return; + } + pthread_mutex_lock((pthread_mutex_t *)&(rwm->mutex)); + if (!rwm->tail || !rwm->head) { // first node + rwm->head = newNode; + rwm->tail = newNode; + newNode->next = NULL; + newNode->prev = NULL; + } else { + newNode->prev = rwm->tail; + newNode->next = NULL; + rwm->tail->next = newNode; + rwm->tail = newNode; + } + pthread_mutex_unlock((pthread_mutex_t *)&(rwm->mutex)); +} + + +// find the node and move out from the list +// return: the pointer of the moved out node +ResultWaitingMsgNode *FindAndMoveWaitingMsg(ResultWaitingMsgList *rwm, uint32_t seqId) +{ + pthread_mutex_lock((pthread_mutex_t *)&(rwm->mutex)); + ResultWaitingMsgNode *r = NULL; + ResultWaitingMsgNode *pc = rwm->head; + while (pc) { + if (pc->reqMsg != NULL && pc->reqMsg->head.seqId == seqId) { + r = MoveFromList(rwm, pc); + break; + } + pc = pc->next; + } + pthread_mutex_unlock((pthread_mutex_t *)&(rwm->mutex)); + return r; +} + +void MoveOutWaitingMsg(ResultWaitingMsgList *rwm, ResultWaitingMsgNode *node) +{ + if (!rwm || !node) { + return; + } + ResultWaitingMsgNode *pc = rwm->head; + pthread_mutex_lock((pthread_mutex_t *)&(rwm->mutex)); + while (pc) { + if (pc == node) { + MoveFromList(rwm, pc); + break; + } + pc = pc->next; + } + pthread_mutex_unlock((pthread_mutex_t *)&(rwm->mutex)); +} + +int WaitingForResponse(const ResultWaitingMsgNode *node) +{ + if (!node) { + return ERR_NULL_POINTER; + } + struct timeval now; + struct timespec outTime; + pthread_mutex_lock((pthread_mutex_t *)&(node->waitMutex)); + gettimeofday(&now, NULL); + outTime.tv_sec = now.tv_sec + WAITING_RESULT_TIME_OUT; + outTime.tv_nsec = now.tv_usec * 1000; + int ret = + pthread_cond_timedwait((pthread_cond_t *)&(node->waitCond), (pthread_mutex_t *)&(node->waitMutex), &outTime); + pthread_mutex_unlock((pthread_mutex_t *)&(node->waitMutex)); + if (ret == ETIMEDOUT) { + return ERR_TIMEOUT; + } else if (ret != 0) { + return ERR_SYS_EXCEPTION; + } + return SUCCESS; +} +int DoRspToWaitingMsg(const ResultWaitingMsgNode *node) +{ + if (!node) { + return ERR_NULL_POINTER; + } + pthread_mutex_lock((pthread_mutex_t *)&(node->waitMutex)); + pthread_cond_signal((pthread_cond_t *)&(node->waitCond)); + pthread_mutex_unlock((pthread_mutex_t *)&(node->waitMutex)); + return SUCCESS; +} \ No newline at end of file diff --git a/common/src/pwrmsg.c b/common/src/pwrmsg.c new file mode 100644 index 0000000..1ace4c7 --- /dev/null +++ b/common/src/pwrmsg.c @@ -0,0 +1,147 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Message struct and operations implementation. These messages used for communication between + * PowerAPI.so and PowerAPI service. + * **************************************************************************** */ +#include "pwrmsg.h" +#include +#include +#include + +static pid_t g_pid = 0; + +static uint32_t GenerateSeqId() +{ + // todo + return 0; +} +static uint32_t GenerateCrcMagic() +{ + // todo + return 0; +} + +static int GenerateReqMsgHead(MsgHead *head, enum OperationType optType, uint32_t dataLen, uint32_t taskNo) +{ + if (!head) { + return ERR_NULL_POINTER; + } + bzero(head, sizeof(MsgHead)); + head->majorVer = MAJOR_VERSION; + head->minorVer = MINOR_VERSION; + head->optType = optType; + head->dataFormat = FMT_BIN; + head->msgType = MT_REQ; + head->rspCode = 0; + head->seqId = GenerateSeqId(); + head->taskNo = taskNo; + head->crcMagic = GenerateCrcMagic(); + head->dataLen = dataLen; + head->sysId = (uint32_t)g_pid; + return SUCCESS; +} + +int GenerateReqMsg(PwrMsg *msg, enum OperationType optType, uint32_t dataLen, uint32_t taskNo, char *data) +{ + if (!msg) { + return ERR_NULL_POINTER; + } + bzero(msg, sizeof(PwrMsg)); + msg->data = data; + return GenerateReqMsgHead(&msg->head, optType, dataLen, taskNo); +} + +PwrMsg *ClonePwrMsg(PwrMsg *msg) +{ + if (!msg) { + return NULL; + } + PwrMsg *c = (PwrMsg *)malloc(sizeof(PwrMsg)); + if (!c) { + return NULL; + } + c->head = msg->head; + if (msg->data) { + char *data = (char *)malloc(sizeof(msg->head.dataLen)); + if (!data) { + free(c); + return NULL; + } + memcpy(data, msg->data, msg->head.dataLen); + c->data = data; + } + return c; +} + +int InitMsgFactory() +{ + g_pid = getpid(); +} + +int GenerateRspMsg(PwrMsg *req, PwrMsg *rsp, int rspCode, char *data, int dataLen) +{ + if (!req || !rsp) { + return ERR_NULL_POINTER; + } + + bzero(rsp, sizeof(PwrMsg)); + rsp->head.majorVer = req->head.majorVer; + rsp->head.minorVer = req->head.minorVer; + rsp->head.optType = req->head.optType; + rsp->head.dataFormat = FMT_BIN; + rsp->head.msgType = MT_RSP; + rsp->head.rspCode = rspCode; + rsp->head.seqId = req->head.seqId; + rsp->head.taskNo = req->head.taskNo; + rsp->head.crcMagic = GenerateCrcMagic(); + ; + rsp->head.dataLen = dataLen; + rsp->head.sysId = req->head.sysId; + rsp->data = data; + return SUCCESS; +} + +void InitThreadInfo(ThreadInfo *threadInfo) +{ + if (!threadInfo) { + return; + } + threadInfo->keepRunning = TRUE; + threadInfo->created = FALSE; + threadInfo->tid = 0; +} + +int CreateThread(ThreadInfo *threadInfo, void *(*thread_proc)(void *)) +{ + if (!threadInfo || !thread_proc) { + return ERR_NULL_POINTER; + } + threadInfo->keepRunning = TRUE; + if (pthread_create(&threadInfo->tid, NULL, thread_proc, NULL) != SUCCESS) { + return ERR_SYS_EXCEPTION; + } + threadInfo->created = TRUE; + return SUCCESS; +} + +void FiniThreadInfo(ThreadInfo *threadInfo) +{ + if (!threadInfo) { + return; + } + threadInfo->keepRunning = FALSE; + if (threadInfo->created == TRUE) { + pthread_join(threadInfo->tid, NULL); + } + threadInfo->created = FALSE; +} \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..cbda411 --- /dev/null +++ b/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd build +sudo make install +sudo systemctl start pwrapis.service \ No newline at end of file diff --git a/pwrapic/CMakeLists.txt b/pwrapic/CMakeLists.txt new file mode 100644 index 0000000..92547e9 --- /dev/null +++ b/pwrapic/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required (VERSION 3.19) +project (powerapic_entrance C) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_subdirectory(src) +add_subdirectory(test) diff --git a/pwrapic/inc/powerapi.h b/pwrapic/inc/powerapi.h new file mode 100644 index 0000000..f6010a9 --- /dev/null +++ b/pwrapic/inc/powerapi.h @@ -0,0 +1,41 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: PowerAPI interface definition. The SI shall include this head file for using the PowerAPI. + * **************************************************************************** */ +#ifndef __POWERAPI_H__ +#define __POWERAPI_H__ + +#include +#include "pwrerr.h" +#include "pwrdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PWR_API + + +// common +PWR_API int PWR_SetLogCallback(void(LogCallback)(int level, const char *fmt, va_list vl)); +PWR_API int PWR_Register(); +PWR_API int PWR_UnRegister(); + +// CPU +PWR_API int PWR_CPU_GetUsage(CPUUsage *usage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pwrapic/inc/pwrcpu.h b/pwrapic/inc/pwrcpu.h new file mode 100644 index 0000000..4e31854 --- /dev/null +++ b/pwrapic/inc/pwrcpu.h @@ -0,0 +1,23 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Provide service for PowerAPI refer to CPU. + * **************************************************************************** */ +#ifndef __POWERAPI_CPU_H__ +#define __POWERAPI_CPU_H__ + +#include "powerapi.h" + +int GetUsage(CPUUsage *usage); + + +#endif diff --git a/pwrapic/inc/pwrlog.h b/pwrapic/inc/pwrlog.h new file mode 100644 index 0000000..27e30da --- /dev/null +++ b/pwrapic/inc/pwrlog.h @@ -0,0 +1,37 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Log service + * **************************************************************************** */ +#ifndef __POWERAPI_LOG_H__ +#define __POWERAPI_LOG_H__ + +#include + +enum PwrLogLevel { + DEBUG = 0, + INFO, + WARNING, + ERROR +}; + +extern void (*PwrLogCallback)(int level, const char *fmt, va_list vl); +static inline void PwrLog(int level, const char *fmt, ...) +{ + if (PwrLogCallback) { + va_list vl; + va_start(vl, fmt); + PwrLogCallback(level, fmt, vl); + va_end(vl); + } +} +#endif diff --git a/pwrapic/inc/sockclient.h b/pwrapic/inc/sockclient.h new file mode 100644 index 0000000..1543a42 --- /dev/null +++ b/pwrapic/inc/sockclient.h @@ -0,0 +1,23 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Provide IPC ability. Socket initialization, send/receive msg, send/recieve buffer + * **************************************************************************** */ +#ifndef __POWERAPI_CONNECTION_H__ +#define __POWERAPI_CONNECTION_H__ +#include "pwrmsg.h" + +int InitSockClient(); +int FiniSockClient(); + +int SendMsgSyn(PwrMsg *msg, PwrMsg **rsp); +#endif diff --git a/pwrapic/src/CMakeLists.txt b/pwrapic/src/CMakeLists.txt new file mode 100644 index 0000000..5fc2031 --- /dev/null +++ b/pwrapic/src/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required (VERSION 3.19) +project (pwrapi C) +set ( CMAKE_INCLUDE_CURRENT_DIR ON) + +# Add head directory +include_directories ("${PROJECT_SOURCE_DIR}/../inc") +include_directories ("${PROJECT_SOURCE_DIR}/../../common/inc") + +# Load source file +aux_source_directory(${PROJECT_SOURCE_DIR}/../../common/src COMMON_SRC) +aux_source_directory(${PROJECT_SOURCE_DIR} PWRAPIC_SRC_DIR) +set(PWRAPIC_SRC ${COMMON_SRC} ${PWRAPIC_SRC_DIR}) + +# Set compile policy +set (PG_NAME ${PROJECT_NAME}) +add_library(${PG_NAME} SHARED ${PWRAPIC_SRC}) +set_target_properties(${PG_NAME} PROPERTIES LINKER_LANGUAGE C) +set (CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# set installation path +set ( CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Install path prefix" FORCE) +#install (TARGETS ${PG_NAME} DESTINATION sbin) +install (TARGETS ${PG_NAME} DESTINATION lib) + +# Release compile mode +#set(CMAKE_BUILD_TYPE "Release") +#set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") + +# Debug compile mode +set(CMAKE_BUILD_TYPE "Debug") +set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") + diff --git a/pwrapic/src/powerapi.c b/pwrapic/src/powerapi.c new file mode 100644 index 0000000..87811b6 --- /dev/null +++ b/pwrapic/src/powerapi.c @@ -0,0 +1,73 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: PowerAPI interface implementation. + * **************************************************************************** */ + +#include "powerapi.h" +#include +#include "pwrlog.h" +#include "sockclient.h" +#include "pwrcpu.h" + +static int g_registed = 0; + +#define CHECK_STATUS \ + if (!g_registed) { \ + PwrLog(ERROR, "Not Registed."); \ + return ERR_NOT_REGISTED; \ + } + +static void DefaultLogCallback(int level, const char *fmt, va_list vl) +{ + printf(fmt); +} + +void (*PwrLogCallback)(int level, const char *fmt, va_list vl) = DefaultLogCallback; + +int PWR_SetLogCallback(void(LogCallback)(int, const char *, va_list)) +{ + if (LogCallback) { + PwrLogCallback = LogCallback; + return 0; + } + return -1; +} + +int PWR_Register() +{ + // todo: 增加必要的其他初始化动作 + if (InitSockClient() != SUCCESS) { + return ERR_COMMON; + } + g_registed = 1; + return SUCCESS; +} + +int PWR_UnRegister() +{ + CHECK_STATUS + int ret = FiniSockClient(); + // todo: 增加必要的其他去初始化动作 + g_registed = 0; + return ret; +} + +int PWR_CPU_GetUsage(CPUUsage *usage) +{ + CHECK_STATUS + if (!usage) { + return ERR_NULL_POINTER; + } + int ret = GetUsage(usage); + return ret; +} diff --git a/pwrapic/src/pwrcpu.c b/pwrapic/src/pwrcpu.c new file mode 100644 index 0000000..9929414 --- /dev/null +++ b/pwrapic/src/pwrcpu.c @@ -0,0 +1,67 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Provide service for PowerAPI refer to CPU. + * **************************************************************************** */ + +#include "pwrcpu.h" +#include +#include "pwrlog.h" +#include "pwrerr.h" +#include "pwrmsg.h" +#include "sockclient.h" + +int GetUsage(CPUUsage *usage) +{ + if (!usage) { + return ERR_NULL_POINTER; + } + // 组装消息 + PwrMsg *msg = (PwrMsg *)malloc(sizeof(PwrMsg)); + if (!msg) { + PwrLog(ERROR, "malloc failed."); + return ERR_COMMON; + } + bzero(msg, sizeof(PwrMsg)); + if (GenerateReqMsg(msg, GET_CPU_USAGE, 0, 0, NULL) != SUCCESS) { + PwrLog(ERROR, "Generate GetUsage req msg failed."); + ReleasePwrMsg(&msg); + return ERR_COMMON; + } + + // 发送消息 + PwrMsg *rsp = NULL; + if (SendMsgSyn(msg, &rsp) != SUCCESS) { + PwrLog(ERROR, "send GET_CPU_USAGE msg failed."); + ReleasePwrMsg(&msg); + ReleasePwrMsg(&rsp); + return ERR_COMMON; + } + + if (rsp == NULL || rsp->head.rspCode != SUCCESS) { + ReleasePwrMsg(&msg); + ReleasePwrMsg(&rsp); + return rsp == NULL ? ERR_COMMON : rsp->head.rspCode; + } + + // 填充结果 + if (rsp->data) { + usage->usage = ((CPUUsage *)(rsp->data))->usage; + } else { + usage->usage = 0; + } + + PwrLog(DEBUG, "GET_CPU_USAGE succeed."); + ReleasePwrMsg(&msg); + ReleasePwrMsg(&rsp); + return SUCCESS; +} diff --git a/pwrapic/src/sockclient.c b/pwrapic/src/sockclient.c new file mode 100644 index 0000000..de9796b --- /dev/null +++ b/pwrapic/src/sockclient.c @@ -0,0 +1,316 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: Provide IPC ability. Socket initialization, send/receive msg, send/recieve buffer + * **************************************************************************** */ + +#include "sockclient.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pwrlog.h" +#include "pwrerr.h" +#include "pwrbuffer.h" + +#define CLIENT_ADDR "pwrclient.sock." +#define SERVER_ADDR "pwrserver.sock" +#define INVALID_FD -1 +#define SOCK_THREAD_LOOP_INTERVAL 2000 // us + +static int g_sockFd = INVALID_FD; +static ThreadInfo g_sockThread; + +static PwrMsgBuffer g_sendBuff; // 发送队列 +static PwrMsgBuffer g_recvBuff; // 接收队列 +static ResultWaitingMsgList g_waitList; // 等待结果列表 + +#define CHECK_SOCKET_STATUS() \ + if (g_sockFd == INVALID_FD) { \ + PwrLog(ERROR, "check socket status failed."); \ + return ERR_DISCONNECTED; \ + } + +static int ReadMsg(void *pData, int len) +{ + int leftLen; + int recvLen; + int readLen = 0; + + leftLen = len; + while (leftLen > 0) { + recvLen = recv(g_sockFd, pData + readLen, leftLen, 0); + if (recvLen < 0) { + PwrLog(ERROR, "recv error %s errno:%d", strerror(errno), errno); + close(g_sockFd); + g_sockFd = INVALID_FD; + return ERR_SYS_EXCEPTION; + } else if (recvLen == 0) { + PwrLog(ERROR, "connection closed !"); + g_sockFd = INVALID_FD; + return ERR_DISCONNECTED; + } + readLen += recvLen; + leftLen -= recvLen; + } + return SUCCESS; +} + +static int WriteMsg(const void *pData, int len) +{ + int leftLen; + int sendLen; + int wrLen = 0; + + leftLen = len; + while (leftLen > 0) { + sendLen = send(g_sockFd, pData + wrLen, leftLen, 0); + if (sendLen < 0) { + PwrLog(ERROR, "send error %s errno:%d", strerror(errno), errno); + close(g_sockFd); + g_sockFd = INVALID_FD; + return ERR_SYS_EXCEPTION; + } + leftLen -= sendLen; + wrLen += sendLen; + } + return SUCCESS; +} + +static void ProcessRspMsg(PwrMsg *rsp) +{ + ResultWaitingMsgNode *rwm = FindAndMoveWaitingMsg(&g_waitList, rsp->head.seqId); + if (!rwm) { + ReleasePwrMsg(&rsp); + return; // drop this msg + } + rwm->rspMsg = rsp; + if (DoRspToWaitingMsg(rwm) != SUCCESS) { + ReleasePwrMsg(&rsp); + return; + } +} + +static void ProcessOtherMsg(PwrMsg *msg) +{ + if (AddToBufferTail(&g_recvBuff, msg) != SUCCESS) { + ReleasePwrMsg(&msg); + } +} + +static void RecvMsgFromSocket() +{ + PwrMsg *msg = (PwrMsg *)malloc(sizeof(PwrMsg)); + if (!msg || ReadMsg(msg, sizeof(PwrMsg)) != SUCCESS) { + ReleasePwrMsg(&msg); + return; + } + + char *msgcontent = malloc(sizeof(msg->head.dataLen)); + if (!msgcontent || ReadMsg(msgcontent, sizeof(msg->head.dataLen)) != SUCCESS) { + ReleasePwrMsg(&msg); + return; + } + msg->data = msgcontent; + + if (msg->head.msgType == MT_RSP) { + ProcessRspMsg(msg); + } else { + ProcessOtherMsg(msg); + } +} + +static void SendMsgToSocket() +{ + int count = 0; + static char data[MAX_DATA_SIZE]; + while (!IsEmptyBuffer(&g_sendBuff) && count < 5) { + PwrMsg *msg = PopFromBufferHead(&g_sendBuff); + count++; + if (!msg) { + continue; + } + int len = sizeof(PwrMsg) + msg->head.dataLen; + + if (len <= MAX_DATA_SIZE) { + memcpy(data, msg, sizeof(PwrMsg)); + memcpy(data + sizeof(PwrMsg), msg->data, msg->head.dataLen); + WriteMsg(data, len); + } else { + memcpy(data, msg, sizeof(PwrMsg)); + memcpy(data + sizeof(PwrMsg), msg->data, MAX_DATA_SIZE - sizeof(PwrMsg)); + WriteMsg(data, MAX_DATA_SIZE); + int datasent = MAX_DATA_SIZE - sizeof(PwrMsg); + int leftLen = len - MAX_DATA_SIZE; + while (leftLen > MAX_DATA_SIZE) { + memcpy(data, msg->data + datasent, MAX_DATA_SIZE); + WriteMsg(data, MAX_DATA_SIZE); + datasent += MAX_DATA_SIZE; + leftLen -= MAX_DATA_SIZE; + } + memcpy(data, msg->data + datasent, leftLen); + WriteMsg(data, leftLen); + } + ReleasePwrMsg(&msg); + } +} + + +static int CreateConnection() +{ + int clientFd; + clientFd = socket(AF_UNIX, SOCK_STREAM, 0); + if (clientFd < 0) { + PwrLog(ERROR, "create socket failed. ret:%d", clientFd); + return ERR_COMMON; + } + // bind + struct sockaddr_un clientAddr; + bzero(&clientAddr, sizeof(clientAddr)); + clientAddr.sun_family = AF_UNIX; + char pidStr[6]; + pid_t pid = getpid(); + sprintf(pidStr, "%d", pid); + strncpy(clientAddr.sun_path, CLIENT_ADDR, sizeof(clientAddr.sun_path) - 1); + // socket file "pwrclient.sock.{$pid}" + strncat(clientAddr.sun_path, pidStr, sizeof(clientAddr.sun_path) - strlen(CLIENT_ADDR) - 1); + int clen = SUN_LEN(&clientAddr); + unlink(clientAddr.sun_path); + if (bind(clientFd, (struct sockaddr *)&clientAddr, clen) < 0) { + PwrLog(ERROR, "bind socket failed."); + close(clientFd); + return ERR_COMMON; + } + // connect + struct sockaddr_un serverAddr; + bzero(&serverAddr, sizeof(serverAddr)); + serverAddr.sun_family = AF_UNIX; + strncpy(serverAddr.sun_path, SERVER_ADDR, sizeof(serverAddr.sun_path) - 1); + int slen = SUN_LEN(&serverAddr); + if (connect(clientFd, (struct sockaddr *)&serverAddr, slen) < 0) { + PwrLog(ERROR, "connect to server failed."); + close(clientFd); + return ERR_COMMON; + } + + g_sockFd = clientFd; + PwrLog(INFO, "connect to server succeed. fd:%d", g_sockFd); + return SUCCESS; +} + +static void *RunSocketProcess() +{ + fd_set recvFdSet; + struct timeval tv; + while (g_sockThread.keepRunning) { + if (g_sockFd == INVALID_FD) { + sleep(3); + CreateConnection(); // resume the connection + continue; + } + + tv.tv_sec = 0; + tv.tv_usec = SOCK_THREAD_LOOP_INTERVAL; + FD_ZERO(&recvFdSet); + FD_SET(g_sockFd, &recvFdSet); + + if (!IsEmptyBuffer(&g_sendBuff)) { + SendMsgToSocket(); + } + + // todo: select中增加断连异常事件监听 + int ret = select(g_sockFd + 1, &recvFdSet, NULL, NULL, &tv); + if (ret > 0 && FD_ISSET(g_sockFd, &recvFdSet)) { + RecvMsgFromSocket(); + } + } // while + return NULL; +} + + +// public****************************************************************************************/ +int InitSockClient() +{ + InitPwrMsgBuffer(&g_sendBuff); + InitPwrMsgBuffer(&g_recvBuff); + InitResultWaitingList(&g_waitList); + InitMsgFactory(); + InitThreadInfo(&g_sockThread); + int ret = SUCCESS; + do { + if (CreateConnection() != SUCCESS) { + ret = ERR_COMMON; + break; + } + int r = CreateThread(&g_sockThread, RunSocketProcess); + if (r != SUCCESS) { + PwrLog(ERROR, "Create recv thread failed. ret[%d]", r); + ret = ERR_COMMON; + break; + } + } while (0); + if (ret != SUCCESS) { + FiniSockClient(); + } + return ret; +} + +int FiniSockClient() +{ + FiniThreadInfo(&g_sockThread); + close(g_sockFd); + ResetPwrMsgBuffer(&g_sendBuff); + ResetPwrMsgBuffer(&g_recvBuff); + ResetResultWaitingList(&g_waitList); + return SUCCESS; +} + +int SendMsgSyn(PwrMsg *msg, PwrMsg **rsp) +{ + if (!msg || !rsp) { + return ERR_NULL_POINTER; + } + CHECK_SOCKET_STATUS(); + + // copy to sending buffer + PwrMsg *copy = ClonePwrMsg(msg); + if (!copy) { + return -1; + } + AddToBufferTail(&g_sendBuff, copy); + + // Waiting for response + ResultWaitingMsgNode *node = CreateResultWaitingMsgNode(); + if (!node) { + PwrLog(ERROR, "Malloc failed."); + ReleasePwrMsg(&msg); + return ERR_SYS_EXCEPTION; + } + node->reqMsg = msg; + AddToWaitingListTail(&g_waitList, node); + int ret = WaitingForResponse(node); + if (ret != SUCCESS) { + // timeout or error scenario. the msg still waiting in the list. need to move out. + MoveOutWaitingMsg(&g_waitList, node); + } + *rsp = node->rspMsg; + node->reqMsg = NULL; + node->rspMsg = NULL; + ReleaseResultWaitingMsgNode(node); + return SUCCESS; +} diff --git a/pwrapic/test/CMakeLists.txt b/pwrapic/test/CMakeLists.txt new file mode 100644 index 0000000..9e8493e --- /dev/null +++ b/pwrapic/test/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required (VERSION 3.19) +project (pwrapic_demo C) +set ( CMAKE_INCLUDE_CURRENT_DIR ON) + +# Add head file directory +include_directories ("${PROJECT_SOURCE_DIR}/../inc") +include_directories ("${PROJECT_SOURCE_DIR}/../../common/inc") + +# Add dependent lib directory +link_directories( ${PROJECT_SOURCE_DIR}/../../build/pwrapic/src ) + +# Set compile policy +set (PG_NAME ${PROJECT_NAME}) +add_executable (${PG_NAME} demo_main.c) +target_link_libraries(${PG_NAME} -lpwrapi) +set (CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set installation path +#set ( CMAKE_INSTALL_PREFIX "/usr/local") +#install (TARGETS ${PG_NAME} DESTINATION lib) + +# Release compile mode +#set(CMAKE_BUILD_TYPE "Release") +#set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") + +# Debug compile mode +set(CMAKE_BUILD_TYPE "Debug") +set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") + diff --git a/pwrapic/test/demo_main.c b/pwrapic/test/demo_main.c new file mode 100644 index 0000000..39aafde --- /dev/null +++ b/pwrapic/test/demo_main.c @@ -0,0 +1,91 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: PowerAPI DEMO for testing the interface. + * **************************************************************************** */ +#include +#include +#include +#include +#include +#include "powerapi.h" + +static int g_run = 1; + +static const char *GetLevelName(int level) +{ + static char debug[] = "DEBUG"; + static char info[] = "INFO"; + static char warning[] = "WARNING"; + static char error[] = "ERROR"; + switch (level) { + case 0: + return debug; + case 1: + return info; + case 2: + return warning; + case 3: + return error; + default: + return info; + } +} + +void LogCallback(int level, const char *fmt, va_list vl) +{ + char logLine[4096] = {0}; + char message[4000] = {0}; + + if (vsnprintf(message, sizeof(message) - 1, fmt, vl) < 0) { + return; + } + + printf("%s: %s\n", GetLevelName(level), message); +} + +static void SignalHandler() +{ + g_run = 0; +} + +static void SetupSignal() +{ + // regist signal handler + signal(SIGINT, SignalHandler); + signal(SIGUSR1, SignalHandler); + signal(SIGUSR2, SignalHandler); + signal(SIGTERM, SignalHandler); + signal(SIGKILL, SignalHandler); +} + +int main(int argc, const char *args[]) +{ + PWR_SetLogCallback(LogCallback); + while (PWR_Register() != SUCCESS) { + sleep(3); + printf("main registed failed!\n"); + continue; + } + printf("main regist succeed.\n"); + CPUUsage u; + bzero(&u, sizeof(CPUUsage)); + PWR_CPU_GetUsage(&u); + printf("CPU usage:%d\n", u.usage); + // todo: 其他接口测试 + + while (g_run) { + sleep(5); + } + PWR_UnRegister(); + return 0; +} \ No newline at end of file diff --git a/pwrapis/conf/pwrapis_config.ini b/pwrapis/conf/pwrapis_config.ini new file mode 100644 index 0000000..a95677e --- /dev/null +++ b/pwrapis/conf/pwrapis_config.ini @@ -0,0 +1,17 @@ +[log] +file_size=1 +cmp_cnt=2 +log_level=0 +log_path=/opt/os_data/log +bak_log_path=/opt/os_data/log/bak +log_pfx=papis.log + +[server] +#port=3028 +sock_file=pwrserver.sock + +#[gather] +#interval=1 +#mnt_point=/opt/os_data/mnt + + diff --git a/pwrapis/inc/common.h b/pwrapis/inc/common.h new file mode 100644 index 0000000..3af8208 --- /dev/null +++ b/pwrapis/inc/common.h @@ -0,0 +1,271 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: luocaimin + * Create: 2021-03-29 + * Description: provide const value defination + * **************************************************************************** */ +#ifndef LCM_COMMON_H +#define LCM_COMMON_H +#define FOUND 0 +#define NOT_FOUND (-1) +#define FAILED (-1) +#define DEFAULT_VAL 0 +#define EMPTY_FD (-1) +#define MAX_PEDDING_SOCKS 5 +#define MS_TO_SEC 1000 +#define ONE_HUNDRED 100 + +// Status code defination +#define INTERACT_SUCCEED 2003 +#define INTERACT_FAIL 2002 +#define NO_PROCESS 2000 +#define PROCESS_EXISTED 2001 +#define GET_UNKNOWN_TYPE 2005 +#define GET_NO_DATA 2006 +#define WRONG_TIME_RANGE 1303 +#define IMPORT_WRONG_DIR_DATA 2007 +#define IMPORT_WRONG_FORMAT_DATA 2008 +#define CRC_FAIL 1202 +#define UNKNOWN_CMD 2009 +#define WRONG_BODY_LEN 2010 +#define WRONG_PATH 1300 +#define WRONG_FORMAT 1301 +#define WRONG_VALUE 1302 +#define LACK_PARAM 1304 +#define UNKNOWN_PARAM 1305 +#define NO_PERMISSION 1201 +#define OVER_GET_DT_LEN 2010 + +// Define module name +#define MD_NM_PST "PERSIST" +#define MD_NM_GTH "GATHER" +#define MD_NM_LOG "LOG" +#define MD_NM_CFG "CONFIG" +#define MD_NM_SGR "SERV_MGR" +#define MD_NM_DSV "DT_SERV" +#define MD_NM_SVR "SERVER" +#define MD_NM_NET "NET" +#define MD_NM_MAN "MAIN" +#define MD_NM_SVR_CPU "CPU_SERVICE" + +// Define configuration section name +#define CFG_NM_PST "persist" +#define CFG_NM_GTH "gather" +#define CFG_NM_LOG "log" +#define CFG_NM_DSV "dt_serv" +#define CFG_NM_SVR "server" +#define CFG_NM_COL "collector" +#define CFG_NM_PRM "param" + +// Define cfg item name +#define CFG_IT_FLT "file_limit" +#define CFG_IT_SPT "space_limit" +#define CFG_IT_DTR "delete_ratio" +#define CFG_IT_DUR "duration" +#define CFG_IT_PTM "path_master" +#define CFG_IT_SLV "path_slave" +#define CFG_IT_PTI "path_import" +#define CFG_IT_FLS "file_size" +#define CFG_IT_CNT "cmp_cnt" +#define CFG_IT_LGV "log_level" +#define CFG_IT_LGP "log_path" +#define CFG_IT_BKP "bak_log_path" +#define CFG_IT_PFX "log_pfx" +#define CFG_IT_SVP "port" +#define CFG_IT_SKF "sock_file" +#define CFG_IT_GIV "interval" +#define CFG_IT_MNT "mnt_point" +#define CFG_IT_IO_DISK "^io.disk[[:digit:]]+$" +#define CFG_IT_NET_ETH "^net.eth[[:digit:]]+$" +#define CFG_IT_PROC_PROC "^proc.proc[[:digit:]]+$" +#define CFG_IT_FS_FILES "^fs.files[[:digit:]]+$" +#define CFG_IT_FS_PRX "fs.files" +#define CFG_IT_FS_PART "^fs.part[[:digit:]]+$" +#define CFG_IT_GML "get_data_max_len" +#define CFG_IT_IPH "imp_file_path" +#define CFG_IT_EPH "exp_file_path" + +// Max line length +#define MAX_LINE_LENGTH 256 +// Max type collect items +#define MAX_TYPE_ITEM_CNT 500 +// Max section name length +#define MAX_SECTION 23 +// Max config name length +#define MAX_NAME 256 +// Max config value length +#define MAX_VALUE 129 +// Max key value length +#define MAX_KEY_LEN 32 +// Max config param value +#define MAX_PARAM_VAL 128 +// Max config data name +#define MAX_DT_NAME 60 +// Max section name length +#define MAX_SEC_NAME 17 +// Max section name length +#define MAX_FILE_NAME 178 +#define MAX_PATH_NAME 128 +#define MAX_FULL_NAME (MAX_FILE_NAME + MAX_PATH_NAME) +// Comment char +#define INI_START_COMMENT_PREFIXES "#" +// Max config line length +#define MAX_LINE_NUM 3000 +// Max log head length +#define MAX_LOG_LINE (MAX_LINE_NUM + MAX_STD_TIME) +// MAX time length +#define MAX_STD_TIME 32 +#define MAX_FULL_TIME 25 +// Gather +#define MAX_PERIOD 3600 +// Sockt connetion closed +#define CONN_CLOSED (-753462) +#define READ_DONE 1 +// Total number of items collected +#define TOTAL_COLL_ITEM_NUM 400 +// The maximum length of the collected value +#define MAX_COLL_DATA 120 +// Time value length +#define TIME_SEC_LEN 20 +#define FILE_TIME_LEN 13 +#define MAX_REGEX 64 +#define MAX_FILE_LINE 256 +// Maximum persistent data length +#define UNIT_FACTOR 1048576 +#define NEED_SWITCH 1 +#define NO_NEED_SWITCH 0 +#define OPENED 1 +#define CLOSED 0 +#define READ_END "nonono" +// Data read buffer length +#define MAX_READ_BUFF 1024 +#define MAX_CP_BUF 1024 +#define CRT_DIR_MODE 0700 +#define CURRENT_DIR "." +#define PARENT_DIR ".." +#define K_TO_M 1024 +// Collected data name separator +#define DATA_NM_SEP '.' +#define DT_NM_SEP_STR "." +#define JIFF_FACTOR 100 +// Cpu node name prefix length +#define CPU_NM_PX_LEN 7 +#define CPU_USG_LINE_NUM 1 +#define CPU_TOTAL_SECS_FIELD_NUM 1 +#define CPU_IDLE_SECS_FIELD_NUM 2 +#define SIGLE_CPU_IDLE_SECS_NUM 5 +#define CPU_LOAD_LINE_NUM 1 +#define CPU_ONE_MIN_LOAD_FIELD_NUM 1 +#define CPU_FIVE_MIN_LOAD_FIELD_NUM 2 +#define CPU_FIFTEEN_MIN_LOAD_FIELD_NUM 3 + +// Memery data location define +#define FIRST_MATCH_LINE 1 +#define MEMINFO_DATA_FIELD_NUM 2 +#define NUMA_MEM_DATA_FIELD_NUM 4 + +// Numa node name perfix length +#define NUMA_NM_PX_LEN 13 +#define ZERO_USAGE "0" +#define ST_CHANGE "2" +#define FLOAT_ZERO_USAGE "0.00" +#define DAY_SECS 86400 +#define FAILED_EXIT (-1) +#define EMPTY_STR "" + +// Persistence module initialization state definition +#define PST_INIT_DONE 1 +#define PST_NOT_INIT 0 +#define TYPE_FIELD_NUM 1 +#define TIME_FIELD_NUM 2 +#define DT_NAME_FIELD_NUM 3 +#define DT_TIME_FIELD_NUM 2 +#define TAIL_LEN_FACTOR 2 +#define BUF_WARN_RATE 2 +#define ERR_CFG_NAME "ERR_CFG_NAME" + +// Message related definition +#define MAX_HEAD_LEN 256 +#define PATH_SEP_STR "/" +#define PATH_SEP_CHAR '/' +#define CPU_NM_PRX "cpu" +#define CPU_NM_LEN 8 +#define CRC_TB_LEN 256 +#define CRC_FACTOR 0xFFFFFFFF +#define CRC_ERROR (-489) +#define CRC_FILE_BUF_LEN 102400 + +#define SEC_TO_USEC 1000000 +enum STATUS { + ST_ERR = 0, + ST_SUCC = 1, + ST_NO_DT = 2, + ST_CRC_ERR +}; + +#define APP_ARGC 2 +#define CRC_RIGHT_SHIFT_BIT 8 + +#define MIN_DT_FILE_SIZE 1 +#define MAX_DT_FILE_SIZE 1024 +#define MIN_SPACE_SIZE 1 +#define MAX_SPACE_SIZE 10240 +#define MIN_DEL_RATIO 1 +#define MAX_DEL_RATIO 50 +#define MIN_DT_FILE_DURATION 1 +#define MAX_DT_FILE_DURATION 100 + +#define MIN_LOG_FILE_SIZE 1 +#define MAX_LOG_FILE_SIZE 100 +#define MIN_LOG_CMP_CNT 1 +#define MAX_LOG_CMP_CNT 1000 +#define MAX_LOG_FILE_SIZE 100 +#define MAX_LOG_TOTAL_SIZE 10000 +#define MIN_LOG_LEVEL 0 +#define MAX_LOG_LEVEL 3 +#define MIN_SV_PORT 1025 +#define MAX_SV_PORT 65535 +#define MAX_FS_TYPE_CNT 64 + +#define MIN_GTH_ITV 1 +#define MAX_GTH_ITV 5 +#define MAX_CT_LEN 104857600 + +#define MIN_COLL_DURATION 1 +#define MAX_COLL_DURATION MAX_PERIOD + +#define STR_LEN_FOR_LONG 22 +#define WRONG_OBJ "coll_item_not_existed" + +enum ExistSt { + NOT_EXIST = 0, + EXIST +}; + +#define NO_MAP "NO_MAP" +#define ERR_VAL "-1" + +enum RunStatus { + EXIT = 0, + KEEP_RUN +}; + + +#define INVALID_FD -1 +#define INVALID_INDEX -1 + +#define MAX_LICENT_NUM 3 +#define THREAD_LOOP_INTERVAL 2000 // us +#define SERVER_ADDR "pwrserver.sock" +#define CLIENT_ADDR "pwrclient.sock." +#define MAX_SYSID_LEN 20 + +#endif diff --git a/pwrapis/inc/config.h b/pwrapis/inc/config.h new file mode 100644 index 0000000..2e32baa --- /dev/null +++ b/pwrapis/inc/config.h @@ -0,0 +1,57 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide configuration service + * **************************************************************************** */ +#ifndef __PAPIS_CONFIG_H__ +#define __PAPIS_CONFIG_H__ +#include +#include +#include "common.h" + +#define DEFAULT_SERVER_ADDR "pwrserver.sock" +#define DEFAULT_LOG_PATH "/opt/os_data/log" +#define DEFAULT_LOG_PATH_BAK "/opt/os_data/log/bak" +#define DEFAULT_LOG_PFX "papis.log" +#define DEFAULT_FILE_SIZE 10 // MB +#define DEFAULT_FILE_NUM 3 + + +// LogCfg +enum LogLevel { + DEBUG = 0, + INFO, + WARNING, + ERROR +}; + +typedef struct LogCfg { + uint64_t maxFileSize; + uint64_t maxCmpCnt; + enum LogLevel logLevel; + char logPath[MAX_PATH_NAME]; + char logBkp[MAX_PATH_NAME]; + char logPfx[MAX_PATH_NAME]; +} LogCfg; + + +// ServCfg +typedef struct ServCfg { + uint16_t port; + char sockFile[MAX_FILE_NAME]; +} ServCfg; + +int InitConfig(); +LogCfg *GetLogCfg(); +ServCfg *GetServCfg(); +int CheckAndUpdateConfig(); +#endif diff --git a/pwrapis/inc/cpuservice.h b/pwrapis/inc/cpuservice.h new file mode 100644 index 0000000..05ffc6d --- /dev/null +++ b/pwrapis/inc/cpuservice.h @@ -0,0 +1,20 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide cpu service + * **************************************************************************** */ +#ifndef __PAPIS_CPU_SERVICE_H__ +#define __PAPIS_CPU_SERVICE_H__ +#include "pwrmsg.h" + +void GetCpuUsage(PwrMsg *req); +#endif diff --git a/pwrapis/inc/log.h b/pwrapis/inc/log.h new file mode 100644 index 0000000..fabd583 --- /dev/null +++ b/pwrapis/inc/log.h @@ -0,0 +1,37 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide log interface + * **************************************************************************** */ +#ifndef __PAPIS_LOG_H__ +#define __PAPIS_LOG_H__ + +#include +#include "common.h" +#include "config.h" + +/** + * InitLogger - do logger initialize operation. + * + * Note: Exit on error + */ + +int InitLogger(); +/** + * Logger - send messages to the system logger + * + * @level: DEBUG < INFO < WARNING < ERROR + */ +void Logger(enum LogLevel level, const char *moduleName, const char *format, ...); + +void ClearLogger(); +#endif diff --git a/pwrapis/inc/pwrclient.h b/pwrapis/inc/pwrclient.h new file mode 100644 index 0000000..41ee1a8 --- /dev/null +++ b/pwrapis/inc/pwrclient.h @@ -0,0 +1,30 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: pwrclient manager. pwrclient refers to the socket connection info. + * **************************************************************************** */ +#ifndef __PAPIS_CLIENT_H__ +#define __PAPIS_CLIENT_H__ + +#include +typedef struct PwrClient { + int fd; + int sysId; +} PwrClient; + +void InitPwrClient(PwrClient clients[]); +int AddToClientList(PwrClient clients[], PwrClient newClient); +int DeleteFromClientList(PwrClient clients[], int idx); +void CloseAllConnections(PwrClient clients[]); +int GetFdBySysId(const PwrClient clients[], uint32_t sysId); +int GetIdxByFd(const PwrClient clients[], int fd); +#endif diff --git a/pwrapis/inc/server.h b/pwrapis/inc/server.h new file mode 100644 index 0000000..abfbace --- /dev/null +++ b/pwrapis/inc/server.h @@ -0,0 +1,31 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide server methods + * **************************************************************************** */ +#ifndef __PAPIS_SERVER_H__ +#define __PAPIS_SERVER_H__ +#include +#include +#include "common.h" +#include "pwrmsg.h" + +/** + * Init and start the server + * Note: return connected socket fd if success; + * return < 1 if failed + */ +int StartServer(); +void StopServer(); +int SendRspMsg(PwrMsg *rsp); + +#endif diff --git a/pwrapis/inc/utils.h b/pwrapis/inc/utils.h new file mode 100644 index 0000000..43f879d --- /dev/null +++ b/pwrapis/inc/utils.h @@ -0,0 +1,218 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: luocaimin + * Create: 2021-03-29 + * Description: provide common methods + * **************************************************************************** */ +#ifndef LCM_UTILS_H +#define LCM_UTILS_H +#include +#include +#include +#include +#include "config.h" + +#define DIR_ENTRY 4 +#define TM_SEC_NUM 6 +#define STC_TM_S_YEAR 1900 +#define MIN_TM_LEN 14 + +// Maximum recursion depth limit +#define MAX_RECU_DP 100 +struct FieldLocation { + const char *fileName; + int lineNum; + int fieldNum; + const char *sep; +}; +/** + * GetCurSec - returns the current time as the number of seconds + * since the Epoch, 1970 - 01 - 01 00:00:00 + 0000 (UTC). + */ +time_t GetCurSec(); + +/** + * Return the current time string in the specified format + */ +const char *GetCurFmtTmStr(const char *fmt, char *strTime, int bufLen); + +/** + * GetCurFullTime - return current time as "%Y - %m - %d %H:%M:%S.mss" + */ +const char *GetCurFullTime(char *fullTime, int bufLen); + +/** + * Return file size + * + * Note: Return zero if it fails + */ +size_t GetFileSize(const char *fileName); + +/** + * StrTime2Sec - Convert strTime with format(20201206134723) to seconds + */ +time_t StrTime2Sec(const char *strTime); +/* + * GetLastDaySec - Get the last second of the day + * @day: YYYYMMDD + */ +time_t GetLastDaySec(const char *day); + +/* + * GetLastDaySec - Get the last second of the current day + */ +time_t GetLastCurDaySec(); +/** + * LcmGetNthField - Find the @nth field separated by @sep in the string + * + * @src : Source string + * @sep : Separating substrings, where each character + * and combination is a separator string + * @nth : the N'th filed + * @pField: filed buf + * Note : return the start position in the @src if success + * return NULL if others + */ +const char *LcmGetNthField(const char *src, const char *sep, int nth, char *pField, size_t bufLen); + +/** + * LcmGetNthLine - Get the @nth line string of the file + * + * Note : return line if success; NULL if failed; + */ +const char *LcmGetNthLine(const char *fileName, int nth, char *lineBuf, size_t bufLen); +/** + * GetVal - Get the value of the @fieldNum'th field in the @lineNum'th line of the file + */ + +const char *GetVal(struct FieldLocation fdLt, char *valBuf, size_t bufLen); + +int GetValAsInt(const char *fileName, int lineNum, int fieldNum, const char *sep); +uint64_t GetValAsULong(const char *fileName, int lineNum, int fieldNum, const char *sep); +float GetValAsFloat(const char *fileName, int lineNum, int fieldNum, const char *sep); + +#define ALLOC_AND_INIT_ZERO(varname, type) \ + do { \ + (varname) = malloc(sizeof(type)); \ + bzero((varname), sizeof(type)); \ + } while (0) + +/** + * RemoveDir - Delete directory + * @depth: recursion depth + */ +int RemoveDir(const char *dirName, int depth); + +/** + * NormalDirFiler - General directory filter + */ +int NormalDirFiler(const struct dirent *item); + +/** + * GetMatchN - Get the Nth matching line in the file + * + * Note: return match line if success; NULL on error + * Non - thread - safe functions + * + */ +const char *GetMatchN(const char *fileName, regex_t *pRegex, int n, char *row, int bufLen); + +/** + * MatchCnt - Returns the number of lines matching + * the regular expression @pRegex in the file content + * Note: return leas than zero on error + */ +int MatchCnt(const char *fileName, regex_t *pRegex); + +// Create a multi - level directory +int MkDirs(const char *sDirName); + +/** + * Crc32 - Return CRC check code + * + * Note: return value need XOR operation with CRC_FACTOR + */ +unsigned int Crc32(unsigned int crc, const void *buffer, unsigned int size); +unsigned int GetCrc32Val(const void *buffer, unsigned int bufSize); +int GetFileCrc32Val(const char *fileName, unsigned int *fileCrc); + +/* + * IsNumStr - Check if the string is a numeric string + * Note: return 1 for sure + */ +int IsNumStr(const char *pStr); +int NumRangeChk(const char *pStr, long min, long max); +int IsPathOk(const char *path); +/* + * ReadNums - Read consecutive numbers from the beginning of the string + * + * IN: + * @pSrc Source string + * @sep Field separator string + * @maxCnt How many digits can be read at most. Nnlimited if @maxCnt == 0 + * @arrLen The length of the integer array of the cache read result + * + * OUT: + * @dts The integer array of the cache read result + * @pArrLen The actual number of integers read + * + * RETURNS: The starting position of the unread part of the string on success; + * NULL on errors + * + */ + +const char *ReadNums(const char *pSrc, const char *sep, int maxCnt, uint64_t dts[], int *pArrLen); + +char *Rtrim(char *str); + +/* + * StrSplit - Split string by delimiter + * + * IN: + * @src Source string + * @sep Delimiter string + * @res Array of string pointers to hold split entries + * @itemNum the len of @res + * + * OUT: + * @res Array of string pointers to hold split entries + * @itemNum the real count of splited entries + * + * RETURNS: On success, return cache pointer, the cache is used to save split entries, + * and needs to be released after the split array is used. + * NULL on errors; + */ +char *StrSplit(const char *src, const char *sep, char **res, int *itemNum); +/* + * StrJoin - Use concatenations to connect string array entries + * + * IN: + * @strArr String array + * @itemNm string entries + * @jionStr Connection string + * @buf String pointer to save the result + * @bufLen string buffer length + * + * RETURNS: pointer point to buf on success; NULL on errors + */ +const char *StrJoin(char **strArr, int itemNum, const char *joinStr, char *buf, int bufLen); +/* + * StrReplace - Replace successive occurrences of @old in the string with a @new + * + * IN: + * @src Source string + * @dest result string point + * @destLen result buffer length + * + * RETURNS: Pointer point to dest on success; NULL on errors + */ +const char *StrReplace(const char *src, const char *old, const char *new, char *dest, int destLen); +#endif diff --git a/pwrapis/pwrapis.service b/pwrapis/pwrapis.service new file mode 100644 index 0000000..83cb707 --- /dev/null +++ b/pwrapis/pwrapis.service @@ -0,0 +1,11 @@ +[Unit] +Description= Power API Service. + +[Service] +ExecStart=/usr/sbin/pwrapis /etc/sysconfig/pwrapis_config.ini +Restart=always +RestartSec=5 +User=root + +[Install] +WantedBy=multi-user.target diff --git a/pwrapis/src/CMakeLists.txt b/pwrapis/src/CMakeLists.txt new file mode 100644 index 0000000..a4dca8e --- /dev/null +++ b/pwrapis/src/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required (VERSION 3.19) +project (pwrapis C) +set ( CMAKE_INCLUDE_CURRENT_DIR ON) +set ( CMAKE_INSTALL_PREFIX "/usr") +# Add head file directory +include_directories ("${PROJECT_SOURCE_DIR}/../inc") +include_directories ("${PROJECT_SOURCE_DIR}/../../common/inc") + +# Load source file +aux_source_directory(${PROJECT_SOURCE_DIR}/../../common/src COMMON_SRC) +aux_source_directory(${PROJECT_SOURCE_DIR} PWRAPIS_SRC_DIR) +set(PWRAPIS_SRC ${COMMON_SRC} ${PWRAPIS_SRC_DIR}) + +# Set compiling policy +set (PG_NAME ${PROJECT_NAME}) +add_executable (${PG_NAME} ${PWRAPIS_SRC}) +set (CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set installaltion path +#set ( CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}") +set ( CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install path prefix" FORCE) +#install (TARGETS ${PG_NAME} DESTINATION bin) +install (TARGETS ${PG_NAME} DESTINATION sbin) + +# Install default config files +install (FILES "${PROJECT_SOURCE_DIR}/../conf/pwrapis_config.ini" DESTINATION /etc/sysconfig) +install (FILES "${PROJECT_SOURCE_DIR}/../pwrapis.service" DESTINATION /usr/lib/systemd/system) + +# release complile mode +#set(CMAKE_BUILD_TYPE "Release") +#set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") + +# debug complile mode +set(CMAKE_BUILD_TYPE "Debug") +set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") + diff --git a/pwrapis/src/config.c b/pwrapis/src/config.c new file mode 100644 index 0000000..dc20296 --- /dev/null +++ b/pwrapis/src/config.c @@ -0,0 +1,121 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: loading config file and manager all config items for the PowerAPI service + * **************************************************************************** */ + +#include "config.h" +#include "string.h" +#include "pwrerr.h" +#include "log.h" + +static struct LogCfg g_logCfg; +inline LogCfg *GetLogCfg() +{ + return (LogCfg *)&g_logCfg; +} + +static struct ServCfg g_servCfg; +inline ServCfg *GetServCfg() +{ + return (ServCfg *)&g_servCfg; +} + +static int InitLogCfg() +{ + bzero(&g_logCfg, sizeof(g_logCfg)); + g_logCfg.logLevel = DEBUG; // todo 发布时修改为INFO + g_logCfg.maxFileSize = DEFAULT_FILE_SIZE * UNIT_FACTOR - MAX_LINE_LENGTH; + g_logCfg.maxCmpCnt = DEFAULT_FILE_NUM; + strncpy(g_logCfg.logPath, DEFAULT_LOG_PATH, sizeof(g_logCfg.logPath) - 1); + strncpy(g_logCfg.logBkp, DEFAULT_LOG_PATH_BAK, sizeof(g_logCfg.logBkp) - 1); + strncpy(g_logCfg.logPfx, DEFAULT_LOG_PFX, sizeof(g_logCfg.logPfx) - 1); + + char strFlRgx[MAX_NAME] = {0}; + if (sprintf(strFlRgx, "^%s-[[:digit:]]{14}.tar.gz$", g_logCfg.logPfx) < 0) { + return ERR_SYS_EXCEPTION; + } + return SUCCESS; +} + +static int LoadConfigFile() +{ + // todo 打开读取文件,解析配置项,校验配置项,有效配置项替换 +} +static int InitServCfg() +{ + strncpy(g_servCfg.sockFile, DEFAULT_SERVER_ADDR, sizeof(g_servCfg.sockFile) - 1); + g_servCfg.port = 0; + return SUCCESS; +} + + +int InitConfig() +{ + int ret = SUCCESS; + // Init by default values + ret = InitLogCfg(); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_CFG, "Init log config failed. ret:%d", ret); + return ret; + } + + ret = InitServCfg(); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_CFG, "Init server config failed. ret:%d", ret); + return ret; + } + + // load config file + ret = LoadConfigFile(); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_CFG, "config file error. ret:%d", ret); + return ret; + } + return SUCCESS; +} + +int CheckAndUpdateConfig() +{ + // todo 检查配置文件是否有更新,有更新则更新系统配置项 +} + +int UpdateLogLevel(enum LogLevel logLevel) +{ + // Need mutex.... + g_logCfg.logLevel = logLevel; + return SUCCESS; +} + +int GetLogLevel() +{ + return g_logCfg.logLevel; +} + +static enum LogLevel CauLeve(int level) +{ + enum LogLevel lgLvl; + switch (level) { + case DEBUG: + lgLvl = DEBUG; + break; + case INFO: + lgLvl = INFO; + break; + case WARNING: + lgLvl = WARNING; + break; + default: + lgLvl = ERROR; + } + return lgLvl; +} diff --git a/pwrapis/src/cpuservice.c b/pwrapis/src/cpuservice.c new file mode 100644 index 0000000..1b02bd6 --- /dev/null +++ b/pwrapis/src/cpuservice.c @@ -0,0 +1,48 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide cpu service + * **************************************************************************** */ + +#include "cpuservice.h" +#include "string.h" +#include "pwrerr.h" +#include "server.h" +#include "pwrdata.h" +#include "log.h" + + +void GetCpuUsage(PwrMsg *req) +{ + if (!req) { + return; + } + Logger(DEBUG, MD_NM_SVR_CPU, "Get GetCpuUsage Req. seqId:%d, sysId:%d", req->head.seqId, req->head.sysId); + int rspCode = SUCCESS; + CPUUsage *rstData = malloc(sizeof(CPUUsage)); + if (!rstData) { + return; + } + rstData->usage = 40; // todo 调用适配层能力获取CPU使用率 + + PwrMsg *rsp = (PwrMsg *)malloc(sizeof(PwrMsg)); + if (!rsp) { + Logger(ERROR, MD_NM_SVR_CPU, "Malloc failed."); + free(rstData); + return; + } + bzero(rsp, sizeof(PwrMsg)); + GenerateRspMsg(req, rsp, rspCode, (char *)rstData, sizeof(CPUUsage)); + if (SendRspMsg(rsp) != SUCCESS) { + ReleasePwrMsg(&rsp); + } +} diff --git a/pwrapis/src/log.c b/pwrapis/src/log.c new file mode 100644 index 0000000..a1bbf77 --- /dev/null +++ b/pwrapis/src/log.c @@ -0,0 +1,221 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide log service + * **************************************************************************** */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "config.h" +#include "pwrerr.h" +#include "utils.h" + +#define CRT_DIR_MODE 0700 + +static FILE *g_pFile = NULL; // todo 需要mutex保护 +static uint32_t g_curSize = 0; +static regex_t g_logCmpFlRgx; + +static FILE *OpenLogFile() +{ + struct stat st; + char fullName[MAX_FULL_NAME] = {0}; + // Create log file + if (sprintf(fullName, "%s/%s", GetLogCfg()->logPath, GetLogCfg()->logPfx) < 0) { + return NULL; + } + g_pFile = fopen(fullName, "a"); + if (stat(fullName, &st) < 0) { + return NULL; + } + g_curSize = st.st_size; + return g_pFile; +} + +static int LogCmpFileFilter(const struct dirent *item) +{ + if (item->d_type == DT_REG) { + if (regexec(&g_logCmpFlRgx, item->d_name, 0, NULL, 0) == 0) { + return 1; + } else { + return 0; + } + } else { + return 0; + } +} +// Release space by deleting the earlier compressed files +static void SpaceChkAndDel() +{ + int cnt; + int fileCnt; + const char *fileName = NULL; + const char *pTmpPth = NULL; + struct dirent **fileList = NULL; + char fullPath[MAX_FILE_NAME] = {0}; + + pTmpPth = GetLogCfg()->logBkp; + fileCnt = scandir(pTmpPth, &fileList, LogCmpFileFilter, alphasort); + cnt = fileCnt > GetLogCfg()->maxCmpCnt ? fileCnt - GetLogCfg()->maxCmpCnt : 0; + // Delete old compressed files + while (fileCnt--) { + if (fileCnt < cnt) { + fileName = fileList[fileCnt]->d_name; + if (sprintf(fullPath, "%s/%s", GetLogCfg()->logBkp, fileName) < 0) { + perror("set full path error!!!"); + } + if (unlink(fullPath) != 0) { + perror("delete file error!!!"); + } + } + free(fileList[fileCnt]); + } + free(fileList); +} + +static int RotateFile() +{ + int ret; + char curTime[MAX_STD_TIME] = {0}; + char cmdLine[MAX_LINE_NUM] = {0}; + char bakName[MAX_FILE_NAME] = {0}; + + if (g_pFile != NULL) { + fclose(g_pFile); + g_pFile = NULL; + } + + GetCurFmtTmStr("%Y%m%d%H%M%S", curTime, sizeof(curTime) - 1); + if (sprintf(bakName, "%s-%s", GetLogCfg()->logPfx, curTime) < 0) { + return ERR_SYS_EXCEPTION; + } + // Compressed file + if (sprintf(cmdLine, " cd %s && mv %s %s && tar zcvf %s.tar.gz %s && rm %s && mv %s.tar.gz %s", + GetLogCfg()->logPath, GetLogCfg()->logPfx, bakName, bakName, bakName, bakName, bakName, + GetLogCfg()->logBkp) < 0) { + return ERR_SYS_EXCEPTION; + } + ret = system(cmdLine); + if (!(ret != -1 && WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) { + return ERR_SYS_EXCEPTION; + } + SpaceChkAndDel(); + // Create new log file + if (OpenLogFile() == NULL) { + return ERR_SYS_EXCEPTION; + } + return SUCCESS; +} + +static const char *GetLevelName(enum LogLevel level) +{ + static char debug[] = "DEBUG"; + static char info[] = "INFO"; + static char warning[] = "WARNING"; + static char error[] = "ERROR"; + switch (level) { + case DEBUG: + return debug; + case INFO: + return info; + case WARNING: + return warning; + case ERROR: + return error; + default: + return info; + } +} + +int InitLogger() +{ + regcomp(&g_logCmpFlRgx, "^", REG_EXTENDED | REG_NOSUB); + + if (access(GetLogCfg()->logPath, F_OK) != 0) { + if (MkDirs(GetLogCfg()->logPath) != SUCCESS) { + perror("access log path failed."); + return ERR_SYS_EXCEPTION; + } + } + if (access(GetLogCfg()->logBkp, F_OK) != 0) { + if (MkDirs(GetLogCfg()->logBkp) != SUCCESS) { + perror("access log path failed."); + return ERR_SYS_EXCEPTION; + } + } + + if (OpenLogFile() == NULL) { + return ERR_COMMON; + } + return SUCCESS; +} + +void ClearLogger() +{ + if (g_pFile != NULL) { + fclose(g_pFile); + } + g_pFile = NULL; + regfree(&g_logCmpFlRgx); + g_curSize = 0; +} + + +// Check head file +void Logger(enum LogLevel level, const char *moduleName, const char *format, ...) +{ + if (level < GetLogCfg()->logLevel || !g_pFile) { + return; + } + + int logLen; + int ret; + va_list valist; + char curTime[MAX_STD_TIME] = {0}; + char logLine[MAX_LOG_LINE] = {0}; + char message[MAX_LINE_NUM] = {0}; + va_start(valist, format); + + if (vsnprintf(message, sizeof(message) - 1, format, valist) < 0) { + return; + } + GetCurFullTime(curTime, sizeof(curTime) - 1); + ret = sprintf(logLine, "%s %s %s: %s\n", curTime, GetLevelName(level), moduleName, message); + if (ret < 0) { + return; + } + if (fputs(logLine, g_pFile) < 0) { + return; + } + if (fflush(g_pFile) < 0) { + return; + } + logLen = strlen(logLine); + g_curSize += logLen; + if (g_curSize > GetLogCfg()->maxFileSize) { + if (RotateFile() != SUCCESS) { + return; + } + } +} diff --git a/pwrapis/src/main_frame.c b/pwrapis/src/main_frame.c new file mode 100644 index 0000000..b5f8359 --- /dev/null +++ b/pwrapis/src/main_frame.c @@ -0,0 +1,100 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: initialize and app enter + * **************************************************************************** */ +#include +#include +#include + +#include "server.h" +#include "config.h" +#include "log.h" + +#define ARGS_NUM 2 +static int g_keepMainRunning; + +static void PrintUsage(const char *args[]) +{ + printf("Usage: %s < config_file_name > \n", args[0]); +} + +static int BaseInit() +{ + int ret = SUCCESS; + ret = InitConfig(); + if (ret != SUCCESS) { + return ret; + } + + ret = InitLogger(); + if (ret != SUCCESS) { + return ret; + } + + // todo 其他必要的初始化 + return SUCCESS; +} + +static void ClearEnv() +{ + // todo:必要的环境清理动作 + ClearLogger(); +} + +static void SignalHandler() +{ + g_keepMainRunning = EXIT; +} + +static void SetupSignal() +{ + // regist signal handler + signal(SIGINT, SignalHandler); + signal(SIGUSR1, SignalHandler); + signal(SIGUSR2, SignalHandler); + signal(SIGTERM, SignalHandler); + signal(SIGKILL, SignalHandler); +} + +int main(int argc, const char *args[]) +{ + int ret; + /* if (argc < ARGS_NUM) { + PrintUsage(args); + return -1; + } */ // todo 增加启动参数,比如指定配置文件路径 + + ret = BaseInit(); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_MAN, "BaseInit failed. ret:%d", ret); + exit(-1); + } + + ret = StartServer(); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_MAN, "Start Server failed. ret:%d", ret); + exit(-1); + } + Logger(INFO, MD_NM_MAN, "Start Server succeed."); + + SetupSignal(); + g_keepMainRunning = KEEP_RUN; + while (g_keepMainRunning) { + sleep(5); + CheckAndUpdateConfig(); + // todo 系统定时任务(比如配置文件更新)触发 + } + StopServer(); + ClearEnv(); + return 0; +} diff --git a/pwrapis/src/pwrclient.c b/pwrapis/src/pwrclient.c new file mode 100644 index 0000000..897206a --- /dev/null +++ b/pwrapis/src/pwrclient.c @@ -0,0 +1,116 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022 All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: pwrclient manager. pwrclient refers to the socket connection info. + * **************************************************************************** */ +#include +#include +#include "pwrclient.h" +#include "pwrerr.h" +#include "common.h" +#include "log.h" + + +static int FindAvailableSlot(PwrClient clients[]) +{ + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (clients[i].fd == INVALID_FD) { + return i; + } + } + return INVALID_INDEX; +} + +static int GetClientIdx(PwrClient clients[], PwrClient newClient) +{ + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (clients[i].sysId == newClient.sysId) { + return i; + } + } + return INVALID_INDEX; +} + +void InitPwrClient(PwrClient clients[]) +{ + for (int i = 0; i < MAX_LICENT_NUM; i++) { + clients[i].fd = INVALID_FD; + clients[i].sysId = INVALID_INDEX; + } +} + +int AddToClientList(PwrClient clients[], PwrClient newClient) +{ + if (newClient.fd == INVALID_FD) { + return ERR_INVALIDE_PARAM; + } + // reconnect scenario, update the fd + int existIdx = GetClientIdx(clients, newClient); + if (existIdx != INVALID_INDEX) { + close(clients[existIdx].fd); + clients[existIdx].fd = newClient.fd; + return SUCCESS; + } + // new client + int index = FindAvailableSlot(clients); + if (index == INVALID_INDEX) { + Logger(ERROR, MD_NM_SVR, "Maximum client num : %d errno :%d\n", MAX_LICENT_NUM, errno); + return ERR_OVER_MAX_CONNECTION; + } else { + clients[index] = newClient; + return SUCCESS; + } +} + + +int DeleteFromClientList(PwrClient clients[], int idx) +{ + if (idx < 0 || idx >= MAX_LICENT_NUM) { + return ERR_INVALIDE_PARAM; + } + close(clients[idx].fd); + clients[idx].fd = INVALID_FD; + clients[idx].sysId = INVALID_INDEX; + return SUCCESS; +} + +void CloseAllConnections(PwrClient clients[]) +{ + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (clients[i].fd == INVALID_FD) { + continue; + } + close(clients[i].fd); + clients[i].fd = INVALID_FD; + clients[i].sysId = INVALID_INDEX; + } +} + +int GetFdBySysId(const PwrClient clients[], uint32_t sysId) +{ + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (clients[i].sysId == sysId) { + return clients[i].fd; + } + } + return INVALID_FD; +} + +int GetIdxByFd(const PwrClient clients[], int fd) +{ + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (clients[i].fd == fd) { + return i; + } + } + return INVALID_INDEX; +} \ No newline at end of file diff --git a/pwrapis/src/server.c b/pwrapis/src/server.c new file mode 100644 index 0000000..dc2b5d4 --- /dev/null +++ b/pwrapis/src/server.c @@ -0,0 +1,399 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: queyanwen + * Create: 2022-06-23 + * Description: provide server methods. socket and threads managerment, send/receive msg. + * **************************************************************************** */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "log.h" +#include "pwrclient.h" +#include "config.h" +#include "pwrbuffer.h" +#include "cpuservice.h" + +static int g_listenFd = -1; +static pthread_mutex_t g_listenFdLock = PTHREAD_MUTEX_INITIALIZER; +ThreadInfo g_sockProcThread; +ThreadInfo g_ServiceThread; + +static PwrClient g_pwrClients[MAX_LICENT_NUM]; // 对该结构的读和写都在一个线程完成,因而不需要加锁 +static PwrMsgBuffer g_sendBuff; // 发送队列 +static PwrMsgBuffer g_recvBuff; // 接收队列 +static pthread_mutex_t g_waitMsgMutex; +static pthread_cond_t g_waitMsgCond; + +static int ListenStart(int sockFd, const struct sockaddr *addr) +{ + int ret; + int reuse = 0x0; + + ret = setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(int)); + if (ret < 0) { + Logger(ERROR, MD_NM_SVR, "set reuse socket error %s errno: %d\n", strerror(errno), errno); + return ERR_SYS_EXCEPTION; + } + ret = bind(sockFd, addr, sizeof(struct sockaddr)); + if (ret < 0) { + Logger(ERROR, MD_NM_SVR, "bind socket error %s errno: %d\n", strerror(errno), errno); + return ERR_SYS_EXCEPTION; + } + + ret = listen(sockFd, MAX_PEDDING_SOCKS); + if (ret < 0) { + Logger(ERROR, MD_NM_SVR, "listen error %s errno: %d\n", strerror(errno), errno); + return ERR_SYS_EXCEPTION; + } + g_listenFd = sockFd; + + return SUCCESS; +} + +static int StartUnxListen(const char *localFileName) +{ + int sockFd = 0; + struct sockaddr_un tSockaddr; + + // Delete the socket file + unlink(localFileName); + bzero(&tSockaddr, sizeof(tSockaddr)); + tSockaddr.sun_family = AF_UNIX; + strcpy(tSockaddr.sun_path, localFileName); + + // Create a socket + sockFd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockFd < 0) { + Logger(ERROR, MD_NM_SVR, "socket error %s errno: %d\n", strerror(errno), errno); + return ERR_SYS_EXCEPTION; + } + return ListenStart(sockFd, (struct sockaddr *)&tSockaddr); +} + +static void StopListen() +{ + pthread_mutex_lock(&g_listenFdLock); + if (g_listenFd < 0) { + return; + } else { + close(g_listenFd); + } + g_listenFd = INVALID_FD; + pthread_mutex_unlock(&g_listenFdLock); +} + +static void AcceptConnection() +{ + Logger(INFO, MD_NM_SVR, "Received connection request."); + int newClientFd; + struct sockaddr_un clientAddr; + socklen_t socklen = sizeof(struct sockaddr_un); + pthread_mutex_lock(&g_listenFdLock); + newClientFd = accept(g_listenFd, (struct sockaddr *)&clientAddr, &socklen); + pthread_mutex_unlock(&g_listenFdLock); + if (newClientFd < 0) { + Logger(ERROR, MD_NM_SVR, "accpet socket error: %s errno :%d, addr:%s", strerror(errno), errno, + clientAddr.sun_path); + return; + } + /* + SetKeepAlive(newClientFd); todo 链路保活,后续完善 */ + PwrClient client; + client.fd = newClientFd; + unsigned char strSysId[MAX_SYSID_LEN] = {0}; + strncpy(strSysId, clientAddr.sun_path + strlen(CLIENT_ADDR), MAX_SYSID_LEN - 1); + client.sysId = atoi(strSysId); + if (AddToClientList(g_pwrClients, client) != SUCCESS) { + Logger(ERROR, MD_NM_SVR, "Reach maximum connections or client existed : %d ", MAX_LICENT_NUM); + close(newClientFd); + } + Logger(INFO, MD_NM_SVR, "Create new connection succeed. fd:%d, sysId:%d", client.fd, client.sysId); +} + +static int ReadMsg(void *pData, int len, int dstFd, int idx) +{ + int leftLen; + int recvLen; + int readLen = 0; + + leftLen = len; + bzero(pData, len); + while (leftLen > 0) { + recvLen = recv(dstFd, pData + readLen, leftLen, 0); + if (recvLen < 0) { + Logger(ERROR, MD_NM_SVR, "recv error %s errno:%d", strerror(errno), errno); + DeleteFromClientList(g_pwrClients, idx); + return ERR_SYS_EXCEPTION; + } else if (recvLen == 0) { + Logger(ERROR, MD_NM_SVR, "connection closed !"); + DeleteFromClientList(g_pwrClients, idx); + return ERR_DISCONNECTED; + } + readLen += recvLen; + leftLen -= recvLen; + } + return SUCCESS; +} + +static void ProcessRecvMsgFromClient(int clientIdx) +{ + // 从connFd获取消息,并送到service队列,等待处理 + int dstFd = g_pwrClients[clientIdx].fd; + PwrMsg *msg = (PwrMsg *)malloc(sizeof(PwrMsg)); + if (!msg || ReadMsg(msg, sizeof(PwrMsg), dstFd, clientIdx) != SUCCESS) { + ReleasePwrMsg(&msg); + return; + } + Logger(DEBUG, MD_NM_SVR, "receivd msg. opt:%d,sysId:%d", msg->head.optType, msg->head.sysId); + + if (msg->head.msgType != MT_REQ) { + ReleasePwrMsg(&msg); // the server accept request msg only. + } + + if (msg->head.dataLen > 0) { + char *msgcontent = malloc(sizeof(msg->head.dataLen)); + if (!msgcontent || ReadMsg(msgcontent, sizeof(msg->head.dataLen), dstFd, clientIdx) != SUCCESS) { + ReleasePwrMsg(&msg); + return; + } + msg->data = msgcontent; + } else { + msg->data = NULL; + } + + msg->head.sysId = g_pwrClients[clientIdx].sysId; + if (AddToBufferTail(&g_recvBuff, msg) != SUCCESS) { + ReleasePwrMsg(&msg); + } + // activate RunServiceProcess + pthread_mutex_lock((pthread_mutex_t *)&g_waitMsgMutex); + pthread_cond_signal((pthread_cond_t *)&g_waitMsgCond); + pthread_mutex_unlock((pthread_mutex_t *)&g_waitMsgMutex); +} + +static int WriteMsg(const void *pData, int len, int dstFd) +{ + int leftLen; + int sendLen; + int wrLen = 0; + + leftLen = len; + while (leftLen > 0) { + sendLen = send(dstFd, pData + wrLen, leftLen, 0); + if (sendLen < 0) { + Logger(ERROR, MD_NM_SVR, "send error %s errno:%d", strerror(errno), errno); + DeleteFromClientList(g_pwrClients, GetIdxByFd(g_pwrClients, dstFd)); + return ERR_SYS_EXCEPTION; + } + leftLen -= sendLen; + wrLen += sendLen; + } + return SUCCESS; +} + +static void ProcessSendMsgToClient() +{ + // 从缓存中读取待发送消息,并发送出去 + int count = 0; + static char data[MAX_DATA_SIZE]; + while (!IsEmptyBuffer(&g_sendBuff) && count < 5) { + PwrMsg *msg = PopFromBufferHead(&g_sendBuff); + count++; + if (!msg) { + continue; + } + + int dstFd = GetFdBySysId(g_pwrClients, msg->head.sysId); + if (dstFd == INVALID_FD) { + ReleasePwrMsg(&msg); + continue; + } + int len = sizeof(PwrMsg) + msg->head.dataLen; + + if (len <= MAX_DATA_SIZE) { + memcpy(data, msg, sizeof(PwrMsg)); + memcpy(data + sizeof(PwrMsg), msg->data, msg->head.dataLen); + WriteMsg(data, len, dstFd); + } else { + memcpy(data, msg, sizeof(PwrMsg)); + memcpy(data + sizeof(PwrMsg), msg->data, MAX_DATA_SIZE - sizeof(PwrMsg)); + WriteMsg(data, MAX_DATA_SIZE, dstFd); + int datasent = MAX_DATA_SIZE - sizeof(PwrMsg); + int leftLen = len - MAX_DATA_SIZE; + while (leftLen > MAX_DATA_SIZE) { + memcpy(data, msg->data + datasent, MAX_DATA_SIZE); + WriteMsg(data, MAX_DATA_SIZE, dstFd); + datasent += MAX_DATA_SIZE; + leftLen -= MAX_DATA_SIZE; + } + memcpy(data, msg->data + datasent, leftLen); + WriteMsg(data, leftLen, dstFd); + } + Logger(DEBUG, MD_NM_SVR, "send msg. opt:%d,sysId:%d", msg->head.optType, msg->head.sysId); + ReleasePwrMsg(&msg); + } +} + +/** + * RunServerSocketProcess - Run RunServerSocketProcess + * 1. Accepting connection request + * 2. Receiving msg from or send msg to client FDs + */ +static void *RunServerSocketProcess() +{ + fd_set recvFdSet; + int maxFd = INVALID_FD; + struct timeval tv; + InitPwrClient(g_pwrClients); + while (g_sockProcThread.keepRunning) { + tv.tv_sec = 0; + tv.tv_usec = THREAD_LOOP_INTERVAL; + FD_ZERO(&recvFdSet); + maxFd = g_listenFd; + FD_SET(g_listenFd, &recvFdSet); + + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (g_pwrClients[i].fd != INVALID_FD) { + FD_SET(g_pwrClients[i].fd, &recvFdSet); + maxFd = maxFd < g_pwrClients[i].fd ? g_pwrClients[i].fd : maxFd; + } + } + + if (!IsEmptyBuffer(&g_sendBuff)) { + ProcessSendMsgToClient(); + } + // todo: select中增加断连异常事件监听 + int ret = select(maxFd + 1, &recvFdSet, NULL, NULL, &tv); + if (ret <= 0) { + continue; + } + + if (FD_ISSET(g_listenFd, &recvFdSet)) { // new connection + AcceptConnection(); + } + + for (int i = 0; i < MAX_LICENT_NUM; i++) { + if (FD_ISSET(g_pwrClients[i].fd, &recvFdSet)) { // new msg in + ProcessRecvMsgFromClient(i); + } + } + } // while + + CloseAllConnections(g_pwrClients); +} + +static void WaitForMsg() +{ + struct timeval now; + struct timespec outTime; + pthread_mutex_lock((pthread_mutex_t *)&g_waitMsgMutex); + gettimeofday(&now, NULL); + outTime.tv_sec = now.tv_sec; + outTime.tv_nsec = (now.tv_usec + THREAD_LOOP_INTERVAL) * 1000; + pthread_cond_timedwait((pthread_cond_t *)&g_waitMsgCond, (pthread_mutex_t *)&g_waitMsgMutex, &outTime); + pthread_mutex_unlock((pthread_mutex_t *)&g_waitMsgMutex); +} + +static void ProcessReqMsg(PwrMsg *req) +{ + switch (req->head.optType) { + case GET_CPU_USAGE: + GetCpuUsage(req); + break; + case GET_CPU_CACHE_MISS: + // todo + break; + case GET_CPU_TOP: + // todo + break; + case GET_DISK_IO_RATE: + // todo + break; + default: + break; + } + ReleasePwrMsg(&req); +} + + +/** + * RunServiceProcess - Run RunServiceProcess + * Process the request msg in receiving buffer g_recvBuff + */ +static void *RunServiceProcess() +{ + while (g_ServiceThread.keepRunning) { + if (IsEmptyBuffer(&g_recvBuff)) { + WaitForMsg(); + } + PwrMsg *msg = PopFromBufferHead(&g_recvBuff); + if (!msg) { + continue; + } + ProcessReqMsg(msg); + } // while +} +// public====================================================================================== +// Init Socket. Start listening & accepting +int StartServer() +{ + InitMsgFactory(); + InitPwrMsgBuffer(&g_sendBuff); + InitPwrMsgBuffer(&g_recvBuff); + InitThreadInfo(&g_ServiceThread); + InitThreadInfo(&g_sockProcThread); + pthread_mutex_init((pthread_mutex_t *)&g_waitMsgMutex, NULL); + pthread_cond_init((pthread_cond_t *)&g_waitMsgCond, NULL); + int ret; + ret = StartUnxListen(GetServCfg()->sockFile); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_SVR, "%s Listen failed! ret[%d]", GetServCfg(), ret); + return ERR_SYS_EXCEPTION; + } + + ret = CreateThread(&g_ServiceThread, RunServiceProcess); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_SVR, "Create service thread failed! ret[%d]", ret); + return ERR_SYS_EXCEPTION; + } + + ret = CreateThread(&g_sockProcThread, RunServerSocketProcess); + if (ret != SUCCESS) { + Logger(ERROR, MD_NM_SVR, "Create ServerSocketProcess thread failed! ret[%d]", ret); + return ERR_SYS_EXCEPTION; + } + return SUCCESS; +} + +void StopServer() +{ + FiniThreadInfo(&g_sockProcThread); + FiniThreadInfo(&g_ServiceThread); + StopListen(); + ResetPwrMsgBuffer(&g_sendBuff); + ResetPwrMsgBuffer(&g_recvBuff); + pthread_cond_destroy((pthread_cond_t *)&g_waitMsgCond); + pthread_mutex_destroy((pthread_mutex_t *)&g_waitMsgMutex); +} + +int SendRspMsg(PwrMsg *rsp) +{ + return AddToBufferTail(&g_sendBuff, rsp); +} \ No newline at end of file diff --git a/pwrapis/src/utils.c b/pwrapis/src/utils.c new file mode 100644 index 0000000..d9d5c52 --- /dev/null +++ b/pwrapis/src/utils.c @@ -0,0 +1,791 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + * PowerAPI 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: luocaimin + * Create: 2021-03-29 + * Description: provide common methods + * **************************************************************************** */ +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUCCESS 0 + +static struct timeval GetCurTv() +{ + struct timeval curTime; + gettimeofday(&curTime, NULL); + return curTime; +} +// Check head file +time_t GetCurSec() +{ + struct timeval tv; + tv = GetCurTv(); + return tv.tv_sec; +} + +static const unsigned int g_crcTable[CRC_TB_LEN] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + +const char *GetCurFmtTmStr(const char *fmt, char *strTime, int bufLen) +{ + char strStdTime[MAX_STD_TIME] = {0}; + struct timeval curTime; + struct tm *tmp = NULL; + struct tm tmpTm; + + if (fmt == NULL) { + return NULL; + } + curTime = GetCurTv(); + tmp = localtime_r(&curTime.tv_sec, &tmpTm); + if (strftime(strStdTime, sizeof(strStdTime), fmt, tmp) < 0) { + return NULL; + } + if (strlen(strStdTime) > bufLen - 1) { + return NULL; + } + strcpy(strTime, strStdTime); + return strTime; +} + +// Check head file +const char *GetCurFullTime(char *fullTime, int bufLen) +{ + int res; + char strTime[MAX_FULL_TIME] = {0}; + char strStdTime[MAX_STD_TIME] = {0}; + struct timeval curTime; + struct tm *tmp = NULL; + struct tm tmpTm; + + curTime = GetCurTv(); + + tmp = localtime_r(&curTime.tv_sec, &tmpTm); + if (strftime(strStdTime, sizeof(strStdTime), "%F %T", tmp) < 0) { + return NULL; + } + res = snprintf(strTime, sizeof(strTime) - 1, "%s.%ld", strStdTime, curTime.tv_usec / MS_TO_SEC); + if (res < 0) { + return NULL; + } + if (strlen(strTime) > bufLen - 1) { + return NULL; + } + strcpy(fullTime, strTime); + return fullTime; +} + +size_t GetFileSize(const char *fileName) +{ + int res = 0; + struct stat fileStat; + + if (fileName == NULL || access(fileName, F_OK) != 0) { + return res; + } + bzero(&fileStat, sizeof(fileStat)); + res = stat(fileName, &fileStat); + if (res != 0) { + return 0; + } + return fileStat.st_size; +} + +static int LcmStrptime(const char *strTime, struct tm *pTm) +{ + int inNum; + if (pTm == NULL || strTime == NULL || strlen(strTime) < MIN_TM_LEN || !IsNumStr(strTime)) { + return FAILED; + } + inNum = sscanf(strTime, "%4d%2d%2d%2d%2d%2d", &(pTm->tm_year), &(pTm->tm_mon), &(pTm->tm_mday), &(pTm->tm_hour), + &(pTm->tm_min), &(pTm->tm_sec)); + if (inNum < TM_SEC_NUM) { + return FAILED; + } + pTm->tm_year -= STC_TM_S_YEAR; + pTm->tm_mon -= 1; + return SUCCESS; +} +/** + * StrTime2Sec - Convert strTime with format(20201206134723) to seconds + */ +time_t StrTime2Sec(const char *strTime) +{ + struct tm tmpTm; + + if (strTime == NULL) { + return 0; + } + bzero(&tmpTm, sizeof(struct tm)); + if (LcmStrptime(strTime, &tmpTm) != SUCCESS) { + return 0; + } + return mktime(&tmpTm); +} +time_t GetLastDaySec(const char *day) +{ + char strSec[MAX_FULL_TIME] = {0}; + if (day == NULL) { + return 0; + } + if (snprintf(strSec, sizeof(strSec) - 1, "%s235959", day) < 0) { + return 0; + } + return StrTime2Sec(strSec); +} +time_t GetLastCurDaySec() +{ + const char *pDay = NULL; + char strCurTm[MAX_STD_TIME] = {0}; + pDay = GetCurFmtTmStr("%Y%m%d", strCurTm, sizeof(strCurTm) - 1); + return GetLastDaySec(pDay); +} +/** + * LcmGetNthField - Find the @nth field separated by @sep in the string + * + * @src : Source string + * @sep : Separating substrings, where each character + * and combination is a separator string + * @nth : the N'th filed + * @pField: filed buf + * Note : return the start position in the @src if success + * return NULL if others + */ +const char *LcmGetNthField(const char *src, const char *sep, int nth, char *pField, size_t bufLen) +{ + size_t tmpLen = 0; + const char *ps = src; + const char *ptail = NULL; + + if (src == NULL || sep == NULL || pField == NULL || nth < 1 || bufLen < 0) { + return NULL; + } + ptail = src + strlen(src); + while (ps < ptail && nth--) { + // Find the true starting position + ps += tmpLen; + tmpLen = strspn(ps, sep); + ps = ps + tmpLen; + if (ps >= ptail) { + return NULL; + } + // Calculate effective length + tmpLen = strcspn(ps, sep); + } + if (nth == -1) { + if (bufLen < tmpLen) { + return NULL; + } + strncpy(pField, ps, tmpLen); + pField[tmpLen] = '\0'; + return pField; + } else { + return NULL; + } +} + +/** + * LcmGetNthLine - Get the @nth line string of the file + * + * Note : return line if success; NULL if failed; + */ +const char *LcmGetNthLine(const char *fileName, int nth, char *lineBuf, size_t bufLen) +{ + const char *pRes = NULL; + char line[MAX_LINE_NUM] = {0}; + + if (fileName == NULL || nth < 1 || bufLen < 0) { + return NULL; + } + + FILE *pFile = fopen(fileName, "r"); + if (pFile == NULL) { + return NULL; + } + while (nth--) { + pRes = fgets(line, sizeof(line) - 1, pFile); + if (pRes == NULL) { + if (fclose(pFile) < 0) { + return NULL; + } + return NULL; + } + } + if (fclose(pFile) < 0) { + return NULL; + } + if (bufLen < strlen(line)) { + return NULL; + } + strcpy(lineBuf, line); + return lineBuf; +} + +const char *GetVal(struct FieldLocation fdLt, char *valBuf, size_t bufLen) +{ + const char *pRes = NULL; + char lineBuf[MAX_LINE_NUM] = {0}; + + if (bufLen < 0) { + return NULL; + } + pRes = LcmGetNthLine(fdLt.fileName, fdLt.lineNum, lineBuf, sizeof(lineBuf) - 1); + if (pRes == NULL) { + return NULL; + } + pRes = LcmGetNthField(lineBuf, fdLt.sep, fdLt.fieldNum, valBuf, bufLen); + return pRes; +} + +int GetValAsInt(const char *fileName, int lineNum, int fieldNum, const char *sep) +{ + int res; + const char *pIntRes = NULL; + char sIntRes[MAX_VALUE] = {0}; + struct FieldLocation fdLt; + + fdLt.fileName = fileName; + fdLt.lineNum = lineNum; + fdLt.fieldNum = fieldNum; + fdLt.sep = sep; + + pIntRes = GetVal(fdLt, sIntRes, sizeof(sIntRes) - 1); + if (pIntRes == NULL) { + res = DEFAULT_VAL; + } else { + if (sscanf(pIntRes, "%d", &res) < 0) { + return DEFAULT_VAL; + } + } + return res; +} +uint64_t GetValAsULong(const char *fileName, int lineNum, int fieldNum, const char *sep) +{ + uint64_t res; + const char *pLongRes = NULL; + char sLongRes[MAX_VALUE] = {0}; + struct FieldLocation fdLt; + + fdLt.fileName = fileName; + fdLt.lineNum = lineNum; + fdLt.fieldNum = fieldNum; + fdLt.sep = sep; + + pLongRes = GetVal(fdLt, sLongRes, sizeof(sLongRes) - 1); + if (pLongRes == NULL) { + res = DEFAULT_VAL; + } else { + if (sscanf(pLongRes, "%lu", &res) < 0) { + res = DEFAULT_VAL; + } + } + return res; +} + +float GetValAsFloat(const char *fileName, int lineNum, int fieldNum, const char *sep) +{ + float res = 0; + const char *pFloatRes = NULL; + char sFloatRes[MAX_VALUE] = {0}; + struct FieldLocation fdLt; + + fdLt.fileName = fileName; + fdLt.lineNum = lineNum; + fdLt.fieldNum = fieldNum; + fdLt.sep = sep; + + pFloatRes = GetVal(fdLt, sFloatRes, sizeof(sFloatRes) - 1); + if (pFloatRes == NULL) { + res = DEFAULT_VAL; + } else { + if (sscanf(pFloatRes, "%f", &res) < 0) { + res = DEFAULT_VAL; + } + } + return res; +} + +int RemoveDir(const char *dirName, int dpth) +{ + DIR *dirp = NULL; + struct dirent *dp = NULL; + char curDir[] = CURRENT_DIR; + char upDir[] = PARENT_DIR; + struct stat dirStat; + char tmpDirName[MAX_FULL_NAME] = {0}; + + if (dpth > MAX_RECU_DP) { + return FAILED; + } + ++dpth; + + // The directory name does not exist, return directly + if (dirName == NULL || access(dirName, F_OK) != 0) { + return SUCCESS; + } + + if (stat(dirName, &dirStat) < 0) { + return FAILED; + } + + if (S_ISREG(dirStat.st_mode)) { + // Delete Files + remove(dirName); + } else if (S_ISDIR(dirStat.st_mode)) { + dirp = opendir(dirName); + while ((dp = readdir(dirp)) != NULL) { + if ((strcmp(curDir, dp->d_name) == 0) || (strcmp(upDir, dp->d_name) == 0)) { + continue; + } + sprintf(tmpDirName, "%s/%s", dirName, dp->d_name); + // Recursively delete subdirectories + RemoveDir(tmpDirName, dpth); + } + closedir(dirp); + rmdir(dirName); + } else { + return FAILED; + } + return SUCCESS; +} + +int NormalDirFiler(const struct dirent *item) +{ + if (item->d_type == DIR_ENTRY) { + if (strcmp(item->d_name, CURRENT_DIR) == 0 || strcmp(item->d_name, PARENT_DIR) == 0) { + return 0; + } else { + return 1; + } + } else { + return 0; + } +} + +/** + * MatchCnt - Returns the number of lines matching + * the regular expression @pRegex in the file content + * Note: return less than zero on error + */ +int MatchCnt(const char *fileName, regex_t *pRegex) +{ + int cnt = 0; + FILE *pFile = NULL; + char *pRdRes = NULL; + char line[MAX_LINE_NUM] = {0}; + + if (fileName == NULL || pRegex == NULL) { + return FAILED; + } + if (access(fileName, F_OK | R_OK) != 0) { + return FAILED; + } + pFile = fopen(fileName, "r"); + while (!feof(pFile)) { + pRdRes = fgets(line, sizeof(line) - 1, pFile); + if (pRdRes == NULL || feof(pFile)) { + break; + } + if (regexec(pRegex, line, 0, NULL, 0) == 0) { + ++cnt; + } + } + if (fclose(pFile) < 0) { + return cnt; + } + return cnt; +} + +/** + * GetMatchN - Get the Nth matching line in the file + * + * Note: return match line if success; NULL on error + * Non - thread - safe functions + * + */ +const char *GetMatchN(const char *fileName, regex_t *pRegex, int n, char *row, int bufLen) +{ + int cnt = 0; + FILE *pFile = NULL; + char *pRdRes = NULL; + char line[MAX_LINE_NUM] = {0}; + + if (fileName == NULL || pRegex == NULL) { + return NULL; + } + if (access(fileName, F_OK | R_OK) != 0) { + return NULL; + } + pFile = fopen(fileName, "r"); + while (!feof(pFile)) { + pRdRes = fgets(line, sizeof(line) - 1, pFile); + if (pRdRes == NULL || feof(pFile)) { + break; + } + if (regexec(pRegex, line, 0, NULL, 0) == 0) { + ++cnt; + if (cnt == n) { + break; + } + } + } + if (fclose(pFile)) { + return NULL; + } + if (cnt == n) { + if (strlen(line) > bufLen - 1) { + return NULL; + } else { + strcpy(row, line); + return row; + } + } else { + return NULL; + } +} + +int MkDirs(const char *sDirName) +{ + int i; + int len; + char DirName[MAX_PATH_NAME] = {0}; + + strcpy(DirName, sDirName); + i = strlen(DirName); + len = i; + + if (DirName[len - 1] != PATH_SEP_CHAR) { + strcat(DirName, PATH_SEP_STR); + } + len = strlen(DirName); + for (i = 1; i < len; i++) { + if (DirName[i] == PATH_SEP_CHAR) { + DirName[i] = '\0'; + if (access(DirName, F_OK) == 0) { + DirName[i] = PATH_SEP_CHAR; + continue; + } + if (mkdir(DirName, CRT_DIR_MODE) == -1) { + return FAILED; + } + DirName[i] = PATH_SEP_CHAR; + } + } + return SUCCESS; +} + +unsigned int Crc32(unsigned int crc, const void *buff, unsigned int size) +{ + unsigned int i; + const unsigned char *buffer = buff; + + for (i = 0; i < size; i++) { + crc = g_crcTable[(crc ^ buffer[i]) & 0xff] ^ (crc >> CRC_RIGHT_SHIFT_BIT); + } + return crc; +} + +unsigned int GetCrc32Val(const void *buffer, unsigned int bufSize) +{ + unsigned int crc = CRC_FACTOR; + crc = Crc32(crc, buffer, bufSize); + return crc ^ CRC_FACTOR; +} + +int GetFileCrc32Val(const char *fileName, unsigned int *fileCrc) +{ + int fd = -1; + int nread; + unsigned char buf[CRC_FILE_BUF_LEN]; + unsigned int crc; + + if (fileCrc == NULL) { + return FAILED; + } + crc = *fileCrc; + + if (fileName == NULL || fileCrc == NULL) { + return FAILED; + } + fd = open(fileName, O_RDONLY); + if (fd < 0) { + return FAILED; + } + + while ((nread = read(fd, buf, CRC_FILE_BUF_LEN)) > 0) { + crc = Crc32(crc, buf, nread); + memset(buf, 0, CRC_FILE_BUF_LEN); + } + close(fd); + if (nread < 0) { + return FAILED; + } + *fileCrc = crc ^ CRC_FACTOR; + return SUCCESS; +} + +int IsNumStr(const char *pStr) +{ + int len; + int idx; + if (pStr == NULL) { + return 0; + } + len = strlen(pStr); + for (idx = 0; idx < len; ++idx) { + if (!isdigit(pStr[idx])) { + return 0; + } + } + return 1; +} +int NumRangeChk(const char *pStr, long min, long max) +{ + int tmp; + tmp = 0; + + if (!IsNumStr(pStr)) { + return 0; + } + if (sscanf(pStr, "%d", &tmp) < 0) { + return 0; + } + if (tmp < min || tmp > max) { + return 0; + } + return 1; +} +int IsPathOk(const char *path) +{ + static regex_t pthRgx; + static const char *pPthReg = "^/((\\w|-)+/)*((\\w|-)+)?$"; + + if (path == NULL) { + return WRONG_PATH; + } + regcomp(&pthRgx, pPthReg, REG_EXTENDED | REG_NOSUB); + if (regexec(&pthRgx, path, 0, NULL, 0) != 0) { + return WRONG_PATH; + } + regfree(&pthRgx); + return 1; +} + +/* + * ReadNums - Read consecutive numbers from the beginning of the string + * + * IN: + * @pSrc Source string + * @sep Field separator string + * @maxCnt How many digits can be read at most. Nnlimited if @maxCnt == 0 + * @arrLen The length of the integer array of the cache read result + * + * OUT: + * @dts The integer array of the cache read result + * @pArrLen The actual number of integers read + * + * RETURNS: The starting position of the unread part of the string on success; + * NULL on errors + * + */ + +const char *ReadNums(const char *pSrc, const char *sep, int maxCnt, uint64_t dts[], int *pArrLen) +{ + int readCnt; + const char *numStart = NULL; + const char *readPos = NULL; + + if (pSrc == NULL) { + return NULL; + } + readPos = pSrc; + readCnt = 0; + while (*readPos != '\0') { + if (isdigit(*readPos)) { + if (numStart == NULL) { + numStart = readPos; + } + } else if (index(sep, *readPos) != NULL) { + if (numStart == NULL) { + ++readPos; + continue; + } + // read this num + if (sscanf(numStart, "%lu", &dts[readCnt])) { + return NULL; + } + numStart = NULL; + ++readCnt; + if (readCnt == *pArrLen) { + break; + } + if (maxCnt != 0 && readCnt == maxCnt) { + break; + } + } else { + // Other characters are treated as ending characters + break; + } + ++readPos; + } + if (numStart != NULL && readCnt < *pArrLen && (maxCnt == 0 || readCnt < maxCnt)) { + // read last num + if (sscanf(numStart, "%lu", &dts[readCnt]) < 0) { + return NULL; + } + ++readCnt; + } + *pArrLen = readCnt; + return readPos; +} +// Find the last nonspace postion, return pointer +char *Rtrim(char *s) +{ + if (s == NULL) { + return NULL; + } + char *p = s + strlen(s); + while (p - s > 0 && isspace((unsigned char)(*--p))) { + *p = '\0'; + } + return s; +} + +char *StrSplit(const char *src, const char *sep, char **res, int *itemNum) +{ + int idx; + char *savePtr = NULL; + char *buf = NULL; + char *token = NULL; + + if (src == NULL || sep == NULL || res == NULL || itemNum == NULL) { + return NULL; + } + buf = strdup(src); + idx = 0; + token = strtok_r(buf, sep, &savePtr); + while (token != NULL && idx < *itemNum) { + res[idx] = token; + token = strtok_r(NULL, sep, &savePtr); + ++idx; + } + *itemNum = idx; + return buf; +} +const char *StrJoin(char **strArr, int itemNum, const char *joinStr, char *buf, int bufLen) +{ + int idx; + int sepLen; + int fieldLen; + char *pos = NULL; + char tmpBuf[MAX_LINE_LENGTH] = {0}; + + if (strArr == NULL || itemNum < 1 || buf == NULL || bufLen < 1 || joinStr == NULL) { + return NULL; + } + pos = tmpBuf; + sepLen = strlen(joinStr); + for (idx = 0; idx < itemNum - 1; ++idx) { + if (sprintf(pos, "%s%s", strArr[idx], joinStr) < 0) { + continue; + } + fieldLen = strlen(strArr[idx]); + pos += (fieldLen + sepLen); + } + strcat(pos, strArr[idx]); + if (strlen(tmpBuf) > bufLen) { + return NULL; + } + strcpy(buf, tmpBuf); + return buf; +} + +const char *StrReplace(const char *src, const char *old, const char *new, char *dest, int destLen) +{ + int maxNum; + char **res = NULL; + char *buf = NULL; + const char *pStrRes = NULL; + + if (src == NULL || old == NULL || new == NULL || dest == NULL || destLen < 1) { + return NULL; + } + + maxNum = strlen(src); + res = calloc(maxNum, sizeof(char *)); + buf = StrSplit(src, old, res, &maxNum); + if (buf == NULL) { + free(res); + return NULL; + } + + pStrRes = StrJoin(res, maxNum, new, dest, destLen); + free(buf); + free(res); + return pStrRes; +} diff --git a/uninstall.sh b/uninstall.sh new file mode 100644 index 0000000..60bc5c8 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +#cd build +sudo systemctl stop pwrapis.service +#sudo make uninstall -- Gitee