LCOV - code coverage report
Current view: top level - server/entity_manager - client_entity.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.8 % 177 166
Test Date: 2026-08-12 11:05:07 Functions: 92.9 % 14 13

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "client_entity.h"
      12              : 
      13              : #include <thread>
      14              : 
      15              : #include "entity_manager.h"
      16              : #include "queue_manager.h"
      17              : 
      18              : namespace dgw {
      19              : 
      20           30 : ClientEntity::ClientEntity(const EntityMaterial& material, const uint32_t resIndex)
      21           30 :     : SimpleEntity(material, resIndex), asyncDataState_(AsyncDataState::FSM_ASYNC_DATA_INIT)
      22              : {
      23           30 :     (void)entityDesc_.append(", data state:").append(std::to_string(static_cast<int32_t>(asyncDataState_)));
      24           30 : }
      25              : 
      26           13 : FsmStatus ClientEntity::DoDequeue()
      27              : {
      28           13 :     if (asyncDataState_ == AsyncDataState::FSM_ASYNC_DATA_WAIT) {
      29            1 :         return FsmStatus::FSM_KEEP_STATE;
      30              :     }
      31           12 :     if (asyncDataState_ == AsyncDataState::FSM_ASYNC_DATA_SENT) {
      32            1 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_ENTITY_DONE;
      33            1 :         return FsmStatus::FSM_SUCCESS;
      34              :     }
      35              : 
      36           11 :     asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_WAIT;
      37              :     try {
      38           11 :         InvokeDequeThread();
      39            0 :     } catch (std::exception& e) {
      40            0 :         DGW_LOG_ERROR("create async mem buff thread object failed, %s", e.what());
      41            0 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_INIT;
      42            0 :         return FsmStatus::FSM_FAILED;
      43            0 :     }
      44           11 :     return FsmStatus::FSM_KEEP_STATE;
      45              : }
      46              : 
      47           11 : void ClientEntity::InvokeDequeThread()
      48              : {
      49           11 :     std::thread th(&ClientEntity::DoClientDequeue, this);
      50           11 :     th.detach();
      51           11 : }
      52              : 
      53           13 : void ClientEntity::DoClientDequeue()
      54              : {
      55           13 :     if (DoDequeueMbuf(PtrToPtr<Mbuf*, void*>(&mbuf_)) != FsmStatus::FSM_SUCCESS) {
      56           12 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_INIT;
      57           12 :         return;
      58              :     }
      59              : 
      60            1 :     asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_SENT;
      61              :     // enable AsyncMemDequeue Queue flag
      62            1 :     bqs::QueueManager::GetInstance().enableAsyncMemDequeueFlag();
      63            1 :     const auto bqsRet = bqs::QueueManager::GetInstance().EnqueueAsynMemBuffEvent();
      64            1 :     if (bqsRet != bqs::BQS_STATUS_OK) {
      65            1 :         DGW_LOG_ERROR(
      66              :             "failed to EnqueueAsynMemBuffEvent for entity[%s], ret[%d].", entityDesc_.c_str(),
      67              :             static_cast<int32_t>(bqsRet));
      68              :     }
      69              : }
      70              : 
      71           23 : FsmStatus ClientEntity::DoDequeueMbuf(void** mbufPtr) const
      72              : {
      73           23 :     DGW_LOG_INFO("Entity[%s] Start AsyncMemBuffDeQueueEvent", entityDesc_.c_str());
      74           23 :     const uint32_t deviceId = GetDeviceId();
      75           23 :     const uint32_t queueId = GetQueueId();
      76              : 
      77              :     // q empty idle
      78           23 :     int32_t srcStatus = static_cast<int32_t>(QUEUE_NORMAL);
      79              :     auto ret =
      80           23 :         halQueueGetStatus(deviceId, queueId, QUERY_QUEUE_STATUS, static_cast<uint32_t>(sizeof(uint32_t)), &srcStatus);
      81           23 :     if (ret != DRV_ERROR_NONE) {
      82            4 :         DGW_LOG_WARN("queue[%u] on device[%u] halQueueGetStatus ret=%d", queueId, deviceId, static_cast<int32_t>(ret));
      83            4 :         return (ret == DRV_ERROR_NOT_EXIST) ? FsmStatus::FSM_ERROR_PENDING : FsmStatus::FSM_FAILED;
      84              :     }
      85           19 :     if (srcStatus == static_cast<int32_t>(QUEUE_EMPTY)) {
      86            1 :         DGW_LOG_DEBUG("Entity[%s] has been dequeued to empty", entityDesc_.c_str());
      87            1 :         return FsmStatus::FSM_SRC_EMPTY;
      88              :     }
      89              : 
      90           18 :     DGW_LOG_INFO("Entity[%s] Begin halQueuePeek", entityDesc_.c_str());
      91              :     // get mbuf data
      92           18 :     uint64_t deqLen = 0U;
      93           18 :     ret = halQueuePeek(deviceId, queueId, &deqLen, -1);
      94           18 :     if ((ret != DRV_ERROR_NONE) || (deqLen == 0U)) {
      95            2 :         DGW_LOG_ERROR(
      96              :             "halQueuePeek from queue[%u] in device[%u] failed, ret[%d], deqLen[%lu]", queueId, deviceId,
      97              :             static_cast<int32_t>(ret), deqLen);
      98            2 :         return (ret == DRV_ERROR_NOT_EXIST) ? FsmStatus::FSM_ERROR_PENDING : FsmStatus::FSM_FAILED;
      99              :     }
     100           16 :     DGW_LOG_INFO("Entity[%s] Finish halQueuePeek", entityDesc_.c_str());
     101              : 
     102              :     // alloc mbuf
     103           16 :     Mbuf* mbuf = nullptr;
     104           16 :     int32_t retCode = halMbufAlloc(deqLen, &mbuf);
     105           16 :     if ((retCode != DRV_ERROR_NONE) || (mbuf == nullptr)) {
     106            2 :         DGW_LOG_ERROR("halMbufAlloc fail for entity[%s], size[%zu], ret=[%d].", entityDesc_.c_str(), deqLen, retCode);
     107            2 :         return FsmStatus::FSM_FAILED;
     108              :     }
     109              : 
     110           14 :     const auto dequeRet = FillMbufWithDeque(deqLen, mbuf);
     111           14 :     if (dequeRet != FsmStatus::FSM_SUCCESS) {
     112           12 :         (void)halMbufFree(mbuf);
     113           12 :         return dequeRet;
     114              :     }
     115            2 :     *mbufPtr = mbuf;
     116            2 :     return FsmStatus::FSM_SUCCESS;
     117              : }
     118              : 
     119           14 : FsmStatus ClientEntity::FillMbufWithDeque(const uint64_t deqLen, Mbuf* const mbuf) const
     120              : {
     121              :     // setdatalen
     122           14 :     auto retCode = halMbufSetDataLen(mbuf, deqLen);
     123           14 :     if (retCode != static_cast<int32_t>(DRV_ERROR_NONE)) {
     124            1 :         DGW_LOG_ERROR("Failed to call halMbufSetDataLen for entity[%s], ret=[%d].", entityDesc_.c_str(), retCode);
     125            1 :         return FsmStatus::FSM_FAILED;
     126              :     }
     127              : 
     128              :     // get mbuf head
     129           13 :     void* headBuf = nullptr;
     130           13 :     uint32_t headBufSize = 0U;
     131           13 :     retCode = halMbufGetPrivInfo(mbuf, &headBuf, &headBufSize);
     132           13 :     if (retCode != static_cast<int32_t>(DRV_ERROR_NONE)) {
     133            2 :         DGW_LOG_ERROR("halMbufGetPrivInfo from mbuf for entity[%s] failed, ret is %d.", entityDesc_.c_str(), retCode);
     134            2 :         return FsmStatus::FSM_FAILED;
     135              :     }
     136           11 :     if (headBufSize < MBUF_HEAD_MAX_SIZE) {
     137            1 :         DGW_LOG_ERROR("mbuf head size:%u is invalid.", headBufSize);
     138            1 :         return FsmStatus::FSM_FAILED;
     139              :     }
     140              : 
     141              :     // get mbuf data
     142           10 :     void* dataPtr = nullptr;
     143           10 :     retCode = halMbufGetBuffAddr(mbuf, &dataPtr);
     144           10 :     if ((retCode != static_cast<int32_t>(DRV_ERROR_NONE)) || (dataPtr == nullptr)) {
     145            7 :         DGW_LOG_ERROR("Failed to get data or data is nullptr, retCode[%d].", retCode);
     146            7 :         return FsmStatus::FSM_FAILED;
     147              :     }
     148              : 
     149            3 :     const size_t totalLen = sizeof(struct buff_iovec) + sizeof(struct iovec_info);
     150            3 :     std::unique_ptr<char_t[]> vecUniquePtr(new (std::nothrow) char_t[totalLen], std::default_delete<char_t[]>());
     151            3 :     DGW_CHECK(
     152              :         (vecUniquePtr != nullptr), FsmStatus::FSM_FAILED, "failed to alloc memory for buffIovec, size[%zu].", totalLen);
     153              : 
     154            3 :     buff_iovec* const buffIovec = PtrToPtr<char_t, buff_iovec>(vecUniquePtr.get());
     155            3 :     buffIovec->context_base = headBuf;
     156            3 :     buffIovec->context_len = headBufSize;
     157            3 :     buffIovec->count = 1U;
     158            3 :     buffIovec->ptr[0U].iovec_base = dataPtr;
     159            3 :     buffIovec->ptr[0U].len = deqLen;
     160            3 :     const auto ret = halQueueDeQueueBuff(deviceId_, id_, buffIovec, -1);
     161            3 :     if (ret != DRV_ERROR_NONE) {
     162            1 :         DGW_LOG_ERROR(
     163              :             "halQueueDeQueueBuff queue[%u] on device[%u] fail, ret is %d.", id_, deviceId_, static_cast<int32_t>(ret));
     164            1 :         return FsmStatus::FSM_FAILED;
     165              :     }
     166              : 
     167            2 :     return FsmStatus::FSM_SUCCESS;
     168            3 : }
     169              : 
     170            1 : FsmStatus ClientEntity::ResetSrcState()
     171              : {
     172            1 :     ResetSrcSubState();
     173            1 :     return ChangeState(FsmState::FSM_IDLE_STATE);
     174              : }
     175              : 
     176            1 : void ClientEntity::ResetSrcSubState() { asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_INIT; }
     177              : 
     178           10 : Mbuf* ClientEntity::PrepareMbufToPush(DataObjPtr dataObj) const
     179              : {
     180           10 :     Mbuf* const mbuf = const_cast<Mbuf*>(dataObj->GetMbuf());
     181           10 :     return mbuf;
     182              : }
     183              : 
     184           14 : FsmStatus ClientEntity::DoSendData(Mbuf* const mbuf)
     185              : {
     186           14 :     if (asyncDataState_ == AsyncDataState::FSM_ASYNC_DATA_WAIT) {
     187            1 :         return FsmStatus::FSM_KEEP_STATE;
     188              :     }
     189           13 :     if (asyncDataState_ == AsyncDataState::FSM_ASYNC_DATA_SENT) {
     190            2 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_INIT;
     191            2 :         return FsmStatus::FSM_SUCCESS;
     192              :     }
     193              : 
     194           11 :     asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_WAIT;
     195              :     try {
     196           11 :         InvokeEnqueThread(mbuf);
     197            0 :     } catch (std::exception& e) {
     198            0 :         DGW_LOG_ERROR("create aync mem buff thread object failed, %s", e.what());
     199            0 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_INIT;
     200            0 :         return FsmStatus::FSM_FAILED;
     201            0 :     }
     202           11 :     return FsmStatus::FSM_KEEP_STATE;
     203              : }
     204              : 
     205           11 : void ClientEntity::InvokeEnqueThread(Mbuf* const mbuf)
     206              : {
     207           11 :     std::thread th(&ClientEntity::DoClientEnqueue, this, mbuf);
     208           11 :     th.detach();
     209           11 : }
     210              : 
     211           18 : FsmStatus ClientEntity::DoClientEnqueue(Mbuf* const mbuf)
     212              : {
     213           18 :     DGW_LOG_INFO("Entity[%s] Start AsyncMemBuffEnQueueEvent", entityDesc_.c_str());
     214           18 :     const auto ret = DoEnqueueMbuf(mbuf);
     215           18 :     if (ret != FsmStatus::FSM_SUCCESS) {
     216           16 :         if (ret == FsmStatus::FSM_DEST_FULL) {
     217            2 :             bqs::StatisticManager::GetInstance().DataQueueEnqueueFullStat();
     218              :         } else {
     219           14 :             bqs::StatisticManager::GetInstance().DataQueueEnqueueFailStat();
     220              :         }
     221           16 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_INIT;
     222              :     } else {
     223            2 :         bqs::StatisticManager::GetInstance().DataQueueEnqueueSuccStat();
     224              :         // mask dst aysnc mem entity
     225            2 :         dgw::EntityManager::Instance().SetExistAsyncMemEntity();
     226              :         // enable AsyncMemEnqueue Queue flag
     227            2 :         bqs::QueueManager::GetInstance().enableAsyncMemEnqueueFlag();
     228            2 :         const auto bqsRet = bqs::QueueManager::GetInstance().EnqueueAsynMemBuffEvent();
     229            2 :         if (bqsRet != bqs::BQS_STATUS_OK) {
     230            1 :             DGW_LOG_ERROR("failed to EnqueueAsynMemBuffEvent, ret[%d].", static_cast<int32_t>(bqsRet));
     231              :         }
     232            2 :         asyncDataState_ = AsyncDataState::FSM_ASYNC_DATA_SENT;
     233              :     }
     234           18 :     return ret;
     235              : }
     236              : 
     237           18 : FsmStatus ClientEntity::DoEnqueueMbuf(Mbuf* const mbuf) const
     238              : {
     239              :     // get mbuf head
     240           18 :     void* headBuf = nullptr;
     241           18 :     uint32_t headBufSize = 0U;
     242           18 :     auto ret = halMbufGetPrivInfo(mbuf, &headBuf, &headBufSize);
     243           18 :     if (ret != DRV_ERROR_NONE) {
     244            3 :         DGW_LOG_ERROR("halMbufGetPrivInfo from mbuf failed, ret is %d.", static_cast<int32_t>(ret));
     245            3 :         return FsmStatus::FSM_FAILED;
     246              :     }
     247           15 :     if (headBufSize < MBUF_HEAD_MAX_SIZE) {
     248            1 :         DGW_LOG_ERROR("mbuf head size:%u is invalid.", headBufSize);
     249            1 :         return FsmStatus::FSM_FAILED;
     250              :     }
     251              : 
     252              :     // get mbuf data length
     253           14 :     uint64_t dataLen = 0UL;
     254           14 :     auto retCode = halMbufGetDataLen(mbuf, &dataLen);
     255           14 :     if ((retCode != static_cast<int32_t>(DRV_ERROR_NONE)) || (dataLen == 0)) {
     256            1 :         DGW_LOG_ERROR("Fail to get buff size for mbuf, ret=[%d], dataLen[%lu]", retCode, dataLen);
     257            1 :         return FsmStatus::FSM_FAILED;
     258              :     }
     259              : 
     260              :     // get mbuf data
     261           13 :     void* dataPtr = nullptr;
     262           13 :     retCode = halMbufGetBuffAddr(mbuf, &dataPtr);
     263           13 :     if ((retCode != static_cast<int32_t>(DRV_ERROR_NONE)) || (dataPtr == nullptr)) {
     264            6 :         DGW_LOG_ERROR("Failed to get data or data is nullptr, ret[%d].", retCode);
     265            6 :         return FsmStatus::FSM_FAILED;
     266              :     }
     267              : 
     268            7 :     const size_t totalLen = sizeof(struct buff_iovec) + sizeof(struct iovec_info);
     269            7 :     std::unique_ptr<char_t[]> vecUniquePtr(new (std::nothrow) char_t[totalLen], std::default_delete<char_t[]>());
     270            7 :     DGW_CHECK(
     271              :         (vecUniquePtr != nullptr), FsmStatus::FSM_FAILED, "failed to alloc memory for buffIovec, size[%zu].", totalLen);
     272              : 
     273            7 :     buff_iovec* const buffIovec = PtrToPtr<char_t, buff_iovec>(vecUniquePtr.get());
     274            7 :     buffIovec->context_base = headBuf;
     275            7 :     buffIovec->context_len = headBufSize;
     276            7 :     buffIovec->count = 1U;
     277            7 :     buffIovec->ptr[0U].iovec_base = dataPtr;
     278            7 :     buffIovec->ptr[0U].len = dataLen;
     279            7 :     DGW_LOG_INFO("Entity[%s] Begin halQueueEnQueueBuff", entityDesc_.c_str());
     280            7 :     ret = halQueueEnQueueBuff(deviceId_, id_, buffIovec, -1);
     281            7 :     DGW_LOG_INFO(
     282              :         "entity:[%s] halQueueEnQueueBuff queue id:[%u] device id:[%u] result:[%d].", entityDesc_.c_str(), id_,
     283              :         deviceId_, static_cast<int32_t>(ret));
     284            7 :     if (ret == DRV_ERROR_QUEUE_FULL) {
     285            2 :         DGW_LOG_WARN("halQueueEnQueue queue id:[%u] on device:[%u] FULL!!!!.", id_, deviceId_);
     286            2 :         return FsmStatus::FSM_DEST_FULL;
     287              :     }
     288            5 :     if (ret != DRV_ERROR_NONE) {
     289            3 :         DGW_LOG_ERROR("halQueueEnQueueBuff queue id:[%u] on device:[%u] FAILED!!!!.", id_, deviceId_);
     290            3 :         return (ret == DRV_ERROR_NOT_EXIST) ? FsmStatus::FSM_ERROR_PENDING : FsmStatus::FSM_FAILED;
     291              :     }
     292            2 :     return FsmStatus::FSM_SUCCESS;
     293            7 : }
     294              : 
     295            0 : bool ClientEntity::IsDataPeeked() const { return (asyncDataState_ == AsyncDataState::FSM_ASYNC_ENTITY_DONE); }
     296              : 
     297              : } // namespace dgw
        

Generated by: LCOV version 2.0-1