From 6fb3548e2c8d7dc23ef5d13b4494533073890af1 Mon Sep 17 00:00:00 2001 From: queyanwen Date: Wed, 16 Nov 2022 09:19:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8E=A7=E5=88=B6=E6=9D=83?= =?UTF-8?q?=E7=94=B3=E8=AF=B7/=E9=87=8A=E6=94=BE=E6=8E=A5=E5=8F=A3,?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=AD=E9=93=BE=E8=B5=84=E6=BA=90=E6=B8=85?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +-- common/inc/pwrerr.h | 5 +- common/inc/pwrmsg.h | 2 + pwrapic/inc/powerapi.h | 2 + pwrapic/inc/pwrcom.h | 21 ++++++++ pwrapic/inc/pwrtask.h | 4 +- pwrapic/src/powerapi.c | 104 +++++++++++++++++++++++++------------- pwrapic/src/pwrcom.c | 59 +++++++++++++++++++++ pwrapic/test/demo_main.c | 13 +++-- pwrapis/inc/comservice.h | 23 +++++++++ pwrapis/inc/taskservice.h | 3 +- pwrapis/src/comservice.c | 81 +++++++++++++++++++++++++++++ pwrapis/src/pwrclient.c | 2 - pwrapis/src/server.c | 46 ++++++++++------- pwrapis/src/taskservice.c | 18 ++++++- res/arch.png | Bin 0 -> 55643 bytes 16 files changed, 324 insertions(+), 67 deletions(-) create mode 100644 pwrapic/inc/pwrcom.h create mode 100644 pwrapic/src/pwrcom.c create mode 100644 pwrapis/inc/comservice.h create mode 100644 pwrapis/src/comservice.c create mode 100644 res/arch.png diff --git a/README.md b/README.md index a5a91e9..04c0bfd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Including a power API SO and the Power API Service. #### 软件架构 软件架构说明 - +![代码架构](./res/arch.png) #### 安装教程 @@ -15,9 +15,9 @@ Including a power API SO and the Power API Service. #### 使用说明 -1. xxxx -2. xxxx -3. xxxx +1. 编译:./build.sh +2. 后台运行PowerAPI Service: ./release/pwrapis/pwrapis & +3. 运行PowerAPI demo: ./release/pwrapi_demo/pwrapic_demo #### 参与贡献 diff --git a/common/inc/pwrerr.h b/common/inc/pwrerr.h index 0310725..ac784e0 100644 --- a/common/inc/pwrerr.h +++ b/common/inc/pwrerr.h @@ -28,12 +28,15 @@ enum RtnCode { ERR_INVALIDE_DATATYPE, ERR_CALLBACK_FUNCTION_SHOULD_BE_SET_FIRST, ERR_NOT_REGISTED = 100, + ERR_NOT_AUTHED, ERR_OVER_MAX_CONNECTION, ERR_DISCONNECTED = 300, ERR_WRONG_RESPONSE_FROM_SERVER, ERR_ANSWER_LONGER_THAN_SIZE, ERR_CREATE_TASK_FAILED = 400, ERR_TASK_NOT_EXISTS, - ERR_OVER_MAX_TASK_NUM + ERR_OVER_MAX_TASK_NUM, + ERR_CONTROL_AUTH_REQUESTED, + ERR_CONTROL_AUTH_OWNERED_BY_OTHERS }; #endif diff --git a/common/inc/pwrmsg.h b/common/inc/pwrmsg.h index 75361d5..beb0bd3 100644 --- a/common/inc/pwrmsg.h +++ b/common/inc/pwrmsg.h @@ -49,6 +49,8 @@ enum OperationType { COM_CREATE_DC_TASK = 10, COM_DELETE_DC_TASK, COM_CALLBACK_DATA, + COM_REQUEST_CONTROL_AUTH, + COM_RELEASE_CONTROL_AUTH, SYS_SET_POWER_STATE = 100, CPU_GET_INFO = 200, CPU_GET_USAGE, diff --git a/pwrapic/inc/powerapi.h b/pwrapic/inc/powerapi.h index cf57579..a7d928b 100644 --- a/pwrapic/inc/powerapi.h +++ b/pwrapic/inc/powerapi.h @@ -34,6 +34,8 @@ PWR_API int PWR_UnRegister(void); PWR_API int PWR_SetMetaDataCallback(void(MetaDataCallback)(const PWR_COM_CallbackData *callbackData)); PWR_API int PWR_CreateDcTask(const PWR_COM_BasicDcTaskInfo *basicDcTaskInfo); PWR_API int PWR_DeleteDcTask(PWR_COM_COL_DATATYPE dataType); +PWR_API int PWR_RequestControlAuth(void); +PWR_API int PWR_ReleaseControlAuth(void); // SYS PWR_API int PWR_SYS_SetPowerState(int powerState); diff --git a/pwrapic/inc/pwrcom.h b/pwrapic/inc/pwrcom.h new file mode 100644 index 0000000..4ec6616 --- /dev/null +++ b/pwrapic/inc/pwrcom.h @@ -0,0 +1,21 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-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-11-15 + * Description: Provide service for PowerAPI refer to common function. + * **************************************************************************** */ +#ifndef POWERAPI_COMM_H__ +#define POWERAPI_COMM_H__ + +int RequestControlAuth(void); +int ReleaseControlAuth(void); + +#endif diff --git a/pwrapic/inc/pwrtask.h b/pwrapic/inc/pwrtask.h index 7f23d67..46c6df2 100644 --- a/pwrapic/inc/pwrtask.h +++ b/pwrapic/inc/pwrtask.h @@ -12,8 +12,8 @@ * Create: 2022-11-01 * Description: Provide service for PowerAPI refer to TASK. * **************************************************************************** */ -#ifndef POWERAPI_COMM_H__ -#define POWERAPI_COMM_H__ +#ifndef POWERAPI_TASK_H__ +#define POWERAPI_TASK_H__ #include "pwrdata.h" diff --git a/pwrapic/src/powerapi.c b/pwrapic/src/powerapi.c index 6d26b5b..a908cb8 100644 --- a/pwrapic/src/powerapi.c +++ b/pwrapic/src/powerapi.c @@ -21,19 +21,31 @@ #include "sockclient.h" #include "pwrtask.h" #include "pwrsys.h" +#include "pwrcom.h" #include "pwrcpu.h" #include "pwrdisk.h" #include "pwrnet.h" #include "pwrusb.h" -static int g_registed = 0; - -#define CHECK_STATUS() \ - { \ - if (!g_registed) { \ - PwrLog(ERROR, "Not Registed."); \ - return ERR_NOT_REGISTED; \ - } \ +typedef enum PwrApiStatus { + STATUS_UNREGISTERED = 0, + STATUS_REGISTERTED = 1, + STATUS_AUTHED = 2, +} PwrApiStatus; + +static PwrApiStatus g_status = STATUS_UNREGISTERED; + +#define CHECK_STATUS(s) \ + { \ + if ((s) > g_status) { \ + if ((s) == STATUS_REGISTERTED) { \ + PwrLog(ERROR, "Not Registed."); \ + return ERR_NOT_REGISTED; \ + } else { \ + PwrLog(ERROR, "Not Authorized."); \ + return ERR_NOT_AUTHED; \ + } \ + } \ } #define CHECK_NULL_POINTER(p) \ @@ -65,7 +77,9 @@ int PWR_Register(void) if (InitSockClient() != SUCCESS) { return ERR_COMMON; } - g_registed = 1; + if (g_status == STATUS_UNREGISTERED) { + g_status = STATUS_REGISTERTED; + } return SUCCESS; } @@ -73,7 +87,7 @@ int PWR_UnRegister(void) { int ret = FiniSockClient(); // todo: 增加必要的其他去初始化动作 - g_registed = 0; + g_status = STATUS_UNREGISTERED; return ret; } @@ -88,7 +102,7 @@ int PWR_SetMetaDataCallback(void(MetaDataCallback)(const PWR_COM_CallbackData *) int PWR_CreateDcTask(const PWR_COM_BasicDcTaskInfo *basicDcTaskInfo) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(basicDcTaskInfo); if (basicDcTaskInfo->interval < MIN_DC_INTERVAL || basicDcTaskInfo->interval > MAX_DC_INTERVAL) { @@ -104,14 +118,34 @@ int PWR_CreateDcTask(const PWR_COM_BasicDcTaskInfo *basicDcTaskInfo) int PWR_DeleteDcTask(PWR_COM_COL_DATATYPE dataType) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); return DeleteDcTask(dataType); } +int PWR_RequestControlAuth(void) +{ + CHECK_STATUS(STATUS_REGISTERTED); + int ret = RequestControlAuth(); + if (ret == SUCCESS) { + g_status = STATUS_AUTHED; + } + return ret; +} + +int PWR_ReleaseControlAuth(void) +{ + CHECK_STATUS(STATUS_AUTHED); + int ret = ReleaseControlAuth(); + if (ret == SUCCESS) { + g_status = STATUS_REGISTERTED; + } + return ret; +} + int PWR_SYS_SetPowerState(int powerState) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); if (powerState != MEM && powerState != DISK) { return ERR_INVALIDE_PARAM; } @@ -120,7 +154,7 @@ int PWR_SYS_SetPowerState(int powerState) int PWR_CPU_GetInfo(PWR_CPU_Info *cpuInfo) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(cpuInfo); return GetCpuInfo(cpuInfo); @@ -128,7 +162,7 @@ int PWR_CPU_GetInfo(PWR_CPU_Info *cpuInfo) int PWR_CPU_GetUsage(PWR_CPU_Usage *usage, uint32_t bufferSize) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(usage); if (bufferSize < sizeof(PWR_CPU_Usage)) { return ERR_INVALIDE_PARAM; @@ -139,7 +173,7 @@ int PWR_CPU_GetUsage(PWR_CPU_Usage *usage, uint32_t bufferSize) PWR_API int PWR_CPU_GetPerfData(PWR_CPU_PerfData *perfData) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(perfData); return GetCpuPerfData(perfData); @@ -147,7 +181,7 @@ PWR_API int PWR_CPU_GetPerfData(PWR_CPU_PerfData *perfData) int PWR_CPU_GetFreqAbility(PWR_CPU_FreqAbility *freqAbi, uint32_t bufferSize) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(freqAbi); if (bufferSize < sizeof(PWR_CPU_FreqAbility)) { return ERR_INVALIDE_PARAM; @@ -158,7 +192,7 @@ int PWR_CPU_GetFreqAbility(PWR_CPU_FreqAbility *freqAbi, uint32_t bufferSize) int PWR_CPU_GetFreqGovernor(char gov[], uint32_t size) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(gov); if (size < MAX_ELEMENT_NAME_LEN) { return ERR_INVALIDE_PARAM; @@ -169,7 +203,7 @@ int PWR_CPU_GetFreqGovernor(char gov[], uint32_t size) int PWR_CPU_SetFreqGovernor(char gov[]) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); CHECK_NULL_POINTER(gov); if (strlen(gov) == 0 || strlen(gov) >= MAX_ELEMENT_NAME_LEN) { return ERR_INVALIDE_PARAM; @@ -180,7 +214,7 @@ int PWR_CPU_SetFreqGovernor(char gov[]) int PWR_CPU_GetFreq(PWR_CPU_CurFreq curFreq[], uint32_t *len, int spec) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(curFreq); if (!len || *len == 0 || (spec != TRUE && spec != FALSE)) { return ERR_INVALIDE_PARAM; @@ -191,7 +225,7 @@ int PWR_CPU_GetFreq(PWR_CPU_CurFreq curFreq[], uint32_t *len, int spec) int PWR_CPU_SetFreq(PWR_CPU_CurFreq curFreq[], uint32_t len) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); CHECK_NULL_POINTER(curFreq); if (len == 0) { return ERR_INVALIDE_PARAM; @@ -202,7 +236,7 @@ int PWR_CPU_SetFreq(PWR_CPU_CurFreq curFreq[], uint32_t len) int PWR_CPU_DmaGetLatency(int *latency) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(latency); return GetCpuDmaLatency(latency); @@ -210,7 +244,7 @@ int PWR_CPU_DmaGetLatency(int *latency) int PWR_CPU_DmaSetLatency(int latency) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); if (latency < 0 || latency > MAX_CPU_DMA_LATENCY) { return ERR_INVALIDE_PARAM; } @@ -222,7 +256,7 @@ int PWR_CPU_DmaSetLatency(int latency) // Disk int PWR_DISK_GetList(char diskList[][MAX_ELEMENT_NAME_LEN], uint32_t *len) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(diskList); if (!len || *len == 0) { return ERR_INVALIDE_PARAM; @@ -233,7 +267,7 @@ int PWR_DISK_GetList(char diskList[][MAX_ELEMENT_NAME_LEN], uint32_t *len) int PWR_DISK_GetLoad(PWR_DISK_Load load[], uint32_t *len, int spec) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(load); if (!len || *len == 0 || (spec != TRUE && spec != FALSE)) { return ERR_INVALIDE_PARAM; @@ -244,7 +278,7 @@ int PWR_DISK_GetLoad(PWR_DISK_Load load[], uint32_t *len, int spec) int PWR_DISK_GetPwrLevel(PWR_DISK_PwrLevel pwrLevel[], uint32_t *len, int spec) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(pwrLevel); if (!len || *len == 0 || (spec != TRUE && spec != FALSE)) { return ERR_INVALIDE_PARAM; @@ -255,7 +289,7 @@ int PWR_DISK_GetPwrLevel(PWR_DISK_PwrLevel pwrLevel[], uint32_t *len, int spec) int PWR_DISK_SetPwrLevel(PWR_DISK_PwrLevel pwrLevel[], uint32_t len) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); CHECK_NULL_POINTER(pwrLevel); if (len == 0) { return ERR_INVALIDE_PARAM; @@ -266,7 +300,7 @@ int PWR_DISK_SetPwrLevel(PWR_DISK_PwrLevel pwrLevel[], uint32_t len) int PWR_DISK_GetScsiPolicy(PWR_DISK_ScsiPolicy scsiPolicy[], uint32_t *len, int spec) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(scsiPolicy); if (!len || *len == 0 || (spec != TRUE && spec != FALSE)) { return ERR_INVALIDE_PARAM; @@ -277,7 +311,7 @@ int PWR_DISK_GetScsiPolicy(PWR_DISK_ScsiPolicy scsiPolicy[], uint32_t *len, int int PWR_DISK_SetScsiPolicy(PWR_DISK_ScsiPolicy scsiPolicy[], uint32_t len) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); CHECK_NULL_POINTER(scsiPolicy); if (len == 0) { return ERR_INVALIDE_PARAM; @@ -290,7 +324,7 @@ int PWR_DISK_SetScsiPolicy(PWR_DISK_ScsiPolicy scsiPolicy[], uint32_t len) // NET int PWR_NET_GetInfo(PWR_NET_Info *netInfo, uint32_t bufferSize) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(netInfo); if (bufferSize <= sizeof(PWR_NET_Info)) { return ERR_INVALIDE_PARAM; @@ -301,7 +335,7 @@ int PWR_NET_GetInfo(PWR_NET_Info *netInfo, uint32_t bufferSize) int PWR_NET_GetThrouth(char ethName[], PWR_NET_Through *ethThrough) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(ethName); CHECK_NULL_POINTER(ethThrough); @@ -314,7 +348,7 @@ int PWR_NET_GetThrouth(char ethName[], PWR_NET_Through *ethThrough) int PWR_NET_GetSpeedMod(char ethName[], uint32_t *speedMod) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(ethName); CHECK_NULL_POINTER(speedMod); if (strlen(ethName) == 0 || strlen(ethName) >= MAX_ELEMENT_NAME_LEN) { @@ -325,7 +359,7 @@ int PWR_NET_GetSpeedMod(char ethName[], uint32_t *speedMod) int PWR_NET_SetSpeedMod(char ethName[], uint32_t speedMod) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); CHECK_NULL_POINTER(ethName); // todo 限制speedMod取值 100 1000 10000 return SetNetSpeedMod(ethName, speedMod); @@ -334,7 +368,7 @@ int PWR_NET_SetSpeedMod(char ethName[], uint32_t speedMod) // USB int PWR_USB_GetAutoSuspend(PWR_USB_AutoSuspend usbAts[], uint32_t *len) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_REGISTERTED); CHECK_NULL_POINTER(usbAts); if (!len || *len == 0) { return ERR_INVALIDE_PARAM; @@ -345,7 +379,7 @@ int PWR_USB_GetAutoSuspend(PWR_USB_AutoSuspend usbAts[], uint32_t *len) int PWR_USB_SetAutoSuspend(PWR_USB_AutoSuspend usbAts[], uint32_t len) { - CHECK_STATUS(); + CHECK_STATUS(STATUS_AUTHED); CHECK_NULL_POINTER(usbAts); if (len == 0) { return ERR_INVALIDE_PARAM; diff --git a/pwrapic/src/pwrcom.c b/pwrapic/src/pwrcom.c new file mode 100644 index 0000000..64d6f0c --- /dev/null +++ b/pwrapic/src/pwrcom.c @@ -0,0 +1,59 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-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-11-15 + * Description: Provide service for PowerAPI refer to common function. + * **************************************************************************** */ + +#include "pwrcom.h" +#include "pwrlog.h" +#include "pwrerr.h" +#include "sockclient.h" + +int RequestControlAuth(void) +{ + ReqInputParam input; + input.optType = COM_REQUEST_CONTROL_AUTH; + input.dataLen = 0; + input.data = NULL; + + RspOutputParam output; + output.rspBuffSize = NULL; + output.rspData = NULL; + + int ret = SendReqAndWaitForRsp(input, output); + if (ret != SUCCESS) { + PwrLog(ERROR, "RequestControlAuth failed. ret:%d", ret); + } else { + PwrLog(DEBUG, "RequestControlAuth Succeed."); + } + return ret; +} + +int ReleaseControlAuth(void) +{ + ReqInputParam input; + input.optType = COM_RELEASE_CONTROL_AUTH; + input.dataLen = 0; + input.data = NULL; + + RspOutputParam output; + output.rspBuffSize = NULL; + output.rspData = NULL; + + int ret = SendReqAndWaitForRsp(input, output); + if (ret != SUCCESS) { + PwrLog(ERROR, "ReleaseControlAuth failed. ret:%d", ret); + } else { + PwrLog(DEBUG, "ReleaseControlAuth Succeed."); + } + return ret; +} diff --git a/pwrapic/test/demo_main.c b/pwrapic/test/demo_main.c index 18136b6..218a85c 100644 --- a/pwrapic/test/demo_main.c +++ b/pwrapic/test/demo_main.c @@ -155,7 +155,7 @@ static void TEST_PWR_CPU_GetUsage(void) static void TEST_PWR_CPU_GetPerfData(void) { int ret; - PWR_CPU_PerfData perfData = {0}; + PWR_CPU_PerfData perfData = { 0 }; ret = PWR_CPU_GetPerfData(&perfData); printf("PWR_CPU_GetPerfData ret: %d, IPC: %.8f LLC misses: %.8f \n", ret, perfData.ipc, perfData.llcMiss); } @@ -271,6 +271,12 @@ int main(int argc, const char *args[]) continue; } printf("main regist succeed.\n"); + int ret = PWR_RequestControlAuth(); + if (ret != SUCCESS) { + printf("Request Control Auth failed.\n"); + } else { + printf("Request Control Auth succeed.\n"); + } TEST_PWR_CPU_GetInfo(); // PWR_CPU_GetUsage @@ -285,17 +291,18 @@ int main(int argc, const char *args[]) // PWR_CPU_GetFreqGovernor PWR_CPU_SetFreqGovernor TEST_PWR_CPU_SetAndGetFreqGov(); - TEST_SYS_SetPowerState(); + // TEST_SYS_SetPowerState(); // PWR_CPU_GetCurFreq PWR_CPU_SetCurFreq // TEST_PWR_CPU_SetAndGetCurFreq(); // PWR_CPU_DmaSetLatency PWR_CPU_DmaGetLatency // TEST_PWR_CPU_DmaSetAndGetLatency(); - TEST_PWR_COM_DcTaskMgr(); + // TEST_PWR_COM_DcTaskMgr(); // todo: 其他接口测试 while (g_run) { sleep(MAIN_LOOP_INTERVAL); } + PWR_ReleaseControlAuth(); PWR_UnRegister(); return 0; } \ No newline at end of file diff --git a/pwrapis/inc/comservice.h b/pwrapis/inc/comservice.h new file mode 100644 index 0000000..9bbbbce --- /dev/null +++ b/pwrapis/inc/comservice.h @@ -0,0 +1,23 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-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-11-15 + * Description: provide common service + * **************************************************************************** */ +#ifndef PAPIS_COMM_SERVICE_H__ +#define PAPIS_COMM_SERVICE_H__ +#include +#include "pwrmsg.h" + +void RequestControlAuth(const PwrMsg *req); +void ReleaseControlAuth(const PwrMsg *req); +void CleanControlAuth(uint32_t client); +#endif diff --git a/pwrapis/inc/taskservice.h b/pwrapis/inc/taskservice.h index d4528eb..763eb27 100644 --- a/pwrapis/inc/taskservice.h +++ b/pwrapis/inc/taskservice.h @@ -14,11 +14,12 @@ * **************************************************************************** */ #ifndef PAPIS_TASK_SERVICE_H__ #define PAPIS_TASK_SERVICE_H__ +#include #include "pwrmsg.h" int InitTaskService(void); void FiniTaskService(void); void CreateDataCollTask(const PwrMsg *req); void DeleteDataCollTask(const PwrMsg *req); - +void CleanDataCollTaskByClient(uint32_t client); #endif diff --git a/pwrapis/src/comservice.c b/pwrapis/src/comservice.c new file mode 100644 index 0000000..c9f583e --- /dev/null +++ b/pwrapis/src/comservice.c @@ -0,0 +1,81 @@ +/* ***************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-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-11-15 + * Description: provide common service + * **************************************************************************** */ + +#include "comservice.h" +#include +#include "common.h" +#include "pwrerr.h" +#include "log.h" +#include "pwrdata.h" +#include "server.h" + +static int g_authed = FALSE; +static uint32_t g_authOwner = 0; + +static int DoAuthRequest(uint32_t client) +{ + if (g_authed) { + if (g_authOwner != client) { // 控制权已授予其他应用 + return ERR_CONTROL_AUTH_REQUESTED; + } + return SUCCESS; + } + g_authOwner = client; + g_authed = TRUE; + return SUCCESS; +} + +static int DoAuthRelease(uint32_t client) +{ + if (g_authed && g_authOwner == client) { + g_authOwner = 0; + g_authed = FALSE; + return SUCCESS; + } + + if (!g_authed) { + g_authOwner = 0; + return SUCCESS; + } + return ERR_CONTROL_AUTH_OWNERED_BY_OTHERS; +} + +// public=========================================================================================== +void RequestControlAuth(const PwrMsg *req) +{ + if (!req) { + return; + } + Logger(DEBUG, MD_NM_SVR_TASK, "Get ReqeustControlAuth Req. seqId:%u, sysId:%d", req->head.seqId, req->head.sysId); + + int rspCode = DoAuthRequest(req->head.sysId); + SendRspToClient(req, rspCode, NULL, 0); +} + +void ReleaseControlAuth(const PwrMsg *req) +{ + if (!req) { + return; + } + Logger(DEBUG, MD_NM_SVR_TASK, "Get ReleaseControlAuth Req. seqId:%u, sysId:%d", req->head.seqId, req->head.sysId); + + int rspCode = DoAuthRelease(req->head.sysId); + SendRspToClient(req, rspCode, NULL, 0); +} + +void CleanControlAuth(uint32_t client) +{ + DoAuthRelease(client); +} \ No newline at end of file diff --git a/pwrapis/src/pwrclient.c b/pwrapis/src/pwrclient.c index 8f59f08..7d56eca 100644 --- a/pwrapis/src/pwrclient.c +++ b/pwrapis/src/pwrclient.c @@ -19,7 +19,6 @@ #include "common.h" #include "log.h" - static int FindAvailableSlot(PwrClient clients[]) { for (int i = 0; i < MAX_CLIENT_NUM; i++) { @@ -71,7 +70,6 @@ int AddToClientList(PwrClient clients[], PwrClient newClient) } } - int DeleteFromClientList(PwrClient clients[], int idx) { if (idx < 0 || idx >= MAX_CLIENT_NUM) { diff --git a/pwrapis/src/server.c b/pwrapis/src/server.c index 00b3323..89e68c8 100644 --- a/pwrapis/src/server.c +++ b/pwrapis/src/server.c @@ -31,6 +31,7 @@ #include "sysservice.h" #include "cpuservice.h" #include "taskservice.h" +#include "comservice.h" #include "pwrerr.h" #define COUNT_MAX 5 @@ -131,6 +132,13 @@ static void AcceptConnection(void) Logger(INFO, MD_NM_SVR, "Create new connection succeed. fd:%d, sysId:%d", client.fd, client.sysId); } +static void CleanClientResource(PwrClient *pwrClient, int idx) +{ + CleanControlAuth(pwrClient->sysId); + CleanDataCollTaskByClient(pwrClient->sysId); + DeleteFromClientList(g_pwrClients, idx); +} + static int ReadMsg(void *pData, int len, int dstFd, int idx) { int leftLen; @@ -142,12 +150,15 @@ static int ReadMsg(void *pData, int len, int dstFd, int idx) while (leftLen > 0) { recvLen = recv(dstFd, pData + readLen, leftLen, 0); if (recvLen < 0) { + if (recvLen == EINTR || recvLen == EWOULDBLOCK || recvLen == EAGAIN) { + continue; + } Logger(ERROR, MD_NM_SVR, "recv error %s errno:%d", strerror(errno), errno); - DeleteFromClientList(g_pwrClients, idx); + CleanClientResource(g_pwrClients, idx); return ERR_SYS_EXCEPTION; } else if (recvLen == 0) { Logger(ERROR, MD_NM_SVR, "connection closed !"); - DeleteFromClientList(g_pwrClients, idx); + CleanClientResource(g_pwrClients, idx); return ERR_DISCONNECTED; } readLen += recvLen; @@ -202,9 +213,16 @@ static int WriteMsg(const void *pData, int len, int dstFd) while (leftLen > 0) { sendLen = send(dstFd, pData + wrLen, leftLen, 0); if (sendLen < 0) { + if (sendLen == EINTR || sendLen == EWOULDBLOCK || sendLen == EAGAIN) { + continue; + } Logger(ERROR, MD_NM_SVR, "send error %s errno:%d", strerror(errno), errno); - DeleteFromClientList(g_pwrClients, GetIdxByFd(g_pwrClients, dstFd)); + CleanClientResource(g_pwrClients, GetIdxByFd(g_pwrClients, dstFd)); return ERR_SYS_EXCEPTION; + } else if (sendLen == 0) { + Logger(ERROR, MD_NM_SVR, "connection closed !"); + CleanClientResource(g_pwrClients, GetIdxByFd(g_pwrClients, dstFd)); + return ERR_DISCONNECTED; } leftLen -= sendLen; wrLen += sendLen; @@ -324,6 +342,12 @@ static void ProcessReqMsg(PwrMsg *req) case COM_DELETE_DC_TASK: DeleteDataCollTask(req); break; + case COM_REQUEST_CONTROL_AUTH: + RequestControlAuth(req); + break; + case COM_RELEASE_CONTROL_AUTH: + ReleaseControlAuth(req); + break; case SYS_SET_POWER_STATE: SetSysPowerState(req); break; @@ -345,20 +369,6 @@ static void ProcessReqMsg(PwrMsg *req) case CPU_GET_CUR_FREQ: GetCpuFreq(req); break; - case DISK_GET_IO_RATE: - break; - case DISK_GET_LIST: - break; - case DISK_GET_LOAD: - break; - case DISK_GET_POWER_LEVEL: - break; - case DISK_SET_POWER_LEVEL: - break; - case DISK_GET_SCSI_POLICY: - break; - case DISK_SET_SCSI_POLICY: - break; default: break; } @@ -457,7 +467,7 @@ void SendRspToClient(const PwrMsg *req, int rspCode, char *data, uint32_t len) } } // 本函数会将data指针所指向数据迁移走,调用方勿对data进行释放操作。 -int SendMetadataToClient(uint32_t sysId, char *data, uint32_t len) +int SendMetadataToClient(uint32_t sysId, char *data, uint32_t len) { if (!data && len != 0) { return ERR_INVALIDE_PARAM; diff --git a/pwrapis/src/taskservice.c b/pwrapis/src/taskservice.c index 349242b..aa88aa2 100644 --- a/pwrapis/src/taskservice.c +++ b/pwrapis/src/taskservice.c @@ -27,7 +27,6 @@ #include "cpuservice.h" #include "utils.h" -#define INVALIDE_TASK_ID (-1) #define MAX_TASK_NUM 10 typedef struct CollDataSubscriber { @@ -330,6 +329,18 @@ static void FiniAllTask(void) pthread_mutex_unlock(&g_taskListMutex); } +static int DeleteAllTaskByClient(uint32_t subscriber) +{ + pthread_mutex_lock(&g_taskListMutex); + if (g_taskNum != 0) { + for (int i = 0; i < MAX_TASK_NUM; i++) { + if (g_collTaskList[i]) { + DeleteSubscriber(i, subscriber); + } + } + } + pthread_mutex_unlock(&g_taskListMutex); +} // public====================================================================== int InitTaskService(void) @@ -375,3 +386,8 @@ void DeleteDataCollTask(const PwrMsg *req) int rspCode = DeleteTask(*dataType, req->head.sysId); SendRspToClient(req, rspCode, NULL, 0); } + +void CleanDataCollTaskByClient(uint32_t client) +{ + DeleteAllTaskByClient(client); +} \ No newline at end of file diff --git a/res/arch.png b/res/arch.png new file mode 100644 index 0000000000000000000000000000000000000000..c728c092ae00689e7f4592b9c8283e9ea452bee9 GIT binary patch literal 55643 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 literal 0 HcmV?d00001 -- Gitee