LCOV - code coverage report
Current view: top level - server/entity_manager - group_entity.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 99.5 % 186 185
Test Date: 2026-07-28 10:54:05 Functions: 100.0 % 17 17

            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 "group_entity.h"
      12              : #include "bqs_util.h"
      13              : #include "common/bqs_log.h"
      14              : #include "entity_manager.h"
      15              : #include "strategy/strategy_manager.h"
      16              : 
      17              : namespace dgw {
      18              : 
      19              : namespace {
      20              :     constexpr int64_t GROUP_WAIT_TRANSID_TIMEOUT = -1L;
      21              : }
      22              : 
      23           27 : GroupEntity::GroupEntity(const EntityMaterial &material, const uint32_t resIndex)
      24           27 :     : Entity(material, resIndex), mbufDeviceId_(material.resId), mbufQueueType_(material.queueType)
      25              : {
      26           27 :     groupInfo_.groupId = static_cast<int32_t>(material.id);
      27           27 :     groupInfo_.groupPolicy = material.groupPolicy;
      28           27 :     groupInfo_.timeout = GROUP_WAIT_TRANSID_TIMEOUT;
      29           27 :     groupInfo_.lastTransId = 0UL;
      30           27 :     groupInfo_.peerInstanceNum = material.peerInstanceNum;
      31           27 :     groupInfo_.localInstanceIndex = material.localInstanceIndex;
      32           27 :     groupInfo_.lastTimestamp = 0UL;
      33           27 : }
      34              : 
      35           10 : FsmStatus GroupEntity::Dequeue()
      36              : {
      37           10 :     const auto dequeAllow = AllowDeque();
      38           10 :     if (dequeAllow != FsmStatus::FSM_SUCCESS) {
      39            2 :         return dequeAllow;
      40              :     }
      41              : 
      42              :     // select src entity in group
      43            8 :     FsmStatus selectStatus = FsmStatus::FSM_SUCCESS;
      44            8 :     const EntityPtr srcEntityPtr = SelectSrcEntity(selectStatus);
      45            8 :     if (selectStatus == FsmStatus::FSM_ERROR) {
      46            1 :         return FsmStatus::FSM_ERROR_PENDING;
      47              :     }
      48              :     // if select failed, group entity change to idle state
      49            7 :     if (srcEntityPtr == nullptr) {
      50            6 :         return FsmStatus::FSM_FAILED;
      51              :     }
      52              : 
      53              :     // select success
      54            1 :     DGW_LOG_INFO("Set srcEntity[%u] entity[%u] transId to %lu, routelabel to %u",
      55              :         srcEntityPtr->GetId(), id_, srcEntityPtr->GetTransId(), srcEntityPtr->GetRouteLabel());
      56            1 :     transId_ = srcEntityPtr->GetTransId();
      57            1 :     routeLabel_ = srcEntityPtr->GetRouteLabel();
      58            1 :     mbufDeviceId_ = srcEntityPtr->GetMbufDeviceId();
      59            1 :     mbufQueueType_ = srcEntityPtr->GetMbufQueueType();
      60            1 :     mbuf_ = srcEntityPtr->GetMbuf();
      61            1 :     srcEntityPtr->ResetSrcState();
      62              :     // set last trans id and last timestamp
      63            1 :     SetGroupInfo(GetTransId(), bqs::GetNowTime());
      64            1 :     AddScheduleCount();
      65            1 :     return FsmStatus::FSM_SUCCESS;
      66            8 : }
      67              : 
      68           13 : EntityPtr GroupEntity::SelectSrcEntity(FsmStatus &status)
      69              : {
      70           13 :     const std::vector<EntityPtr> &entitiesInGroup = EntityManager::Instance(resIndex_).GetEntitiesInGroup(id_);
      71           13 :     if (entitiesInGroup.empty()) {
      72            2 :         DGW_LOG_ERROR("No entities in group, group id:%u", id_);
      73            2 :         return nullptr;
      74              :     }
      75              : 
      76              :     uint64_t waitTransId;
      77              :     // first schedule, set lastTimestamp
      78           11 :     if (groupInfo_.lastTransId == 0UL) {
      79            9 :         SetGroupInfo(0UL, bqs::GetNowTime());
      80           18 :         waitTransId = (groupInfo_.localInstanceIndex == 0U) ?
      81            9 :             groupInfo_.peerInstanceNum : groupInfo_.localInstanceIndex;
      82              :     } else {
      83            2 :         waitTransId = groupInfo_.lastTransId + groupInfo_.peerInstanceNum;
      84              :     }
      85              : 
      86              :     // mark whether all entity in group is peeked state
      87           11 :     bool allFinishPeekFlag = true;
      88              :     // mark whether no entity in group is peeked state
      89           11 :     bool noOneFinishPeekFlag = true;
      90              :     // peek every entity in group
      91           21 :     for (auto &entity : entitiesInGroup) {
      92           14 :         if (entity == nullptr) {
      93            1 :             DGW_LOG_ERROR("Entity is nullptr.");
      94            4 :             return nullptr;
      95              :         }
      96           13 :         DGW_LOG_INFO("[FSM] Begin to peek mbuf from entity[%s] in group:%u, waitTransId:%lu.",
      97              :             entity->ToString().c_str(), id_, waitTransId);
      98              :         
      99              :         // peek data from entity in group
     100           13 :         status = PeekFromEntityInGroup(*entity, waitTransId);
     101           13 :         if (status != FsmStatus::FSM_SUCCESS) {
     102           10 :             if (status == FsmStatus::FSM_ERROR) {
     103            1 :                 DGW_LOG_ERROR("[FSM] Peek mbuf from entity[%s] failed.", entity->ToString().c_str());
     104            1 :                 return nullptr;
     105              :             }
     106            9 :             allFinishPeekFlag = false;
     107            9 :             continue;
     108              :         }
     109            3 :         noOneFinishPeekFlag = false;
     110            3 :         if (Match(*entity, waitTransId, true)) {
     111            2 :             DGW_LOG_DEBUG("[FSM] Entity:[%s] state:[%s] transId:[%lu] has been selected from group entity:[%s].",
     112              :                 entity->ToString().c_str(), entity->GetStateDesc(FsmState::FSM_PEEK_STATE).c_str(),
     113              :                 waitTransId, ToString().c_str());
     114            2 :             return entity;
     115              :         }
     116              :     }
     117              : 
     118              :     // only when part of entities in group are peeked state, check timeout
     119            7 :     bool timeoutFlag = false;
     120            7 :     if ((!allFinishPeekFlag) && (!noOneFinishPeekFlag)) {
     121            1 :         timeoutFlag = CheckTimeout(waitTransId);
     122              :     }
     123              :     // if timeout or all entity in group finished peek, try to find min transId
     124            7 :     if (allFinishPeekFlag || timeoutFlag) {
     125            1 :         return SelectEntityWithMinTransId(entitiesInGroup);
     126              :     }
     127              :     // if not timeout && not all entity in group is peeked state && not exist waitTransId, wait next schedule
     128            6 :     return nullptr;
     129              : }
     130              : 
     131            7 : bool GroupEntity::Match(const Entity &entity, const uint64_t waitTransId, bool exactlyMatch) const {
     132            7 :     if ((entity.GetRouteLabel() != 0U) || (groupInfo_.groupPolicy == bqs::GroupPolicy::DYNAMIC)) {
     133            2 :         return true;
     134              :     }
     135            5 :     DGW_LOG_INFO("entity transid[%lu] vs waitTransId[%lu]", entity.GetTransId(), waitTransId);
     136            5 :     return exactlyMatch ? (entity.GetTransId() == waitTransId) : (entity.GetTransId() >= waitTransId);
     137              : }
     138              : 
     139           13 : FsmStatus GroupEntity::PeekFromEntityInGroup(Entity &entity, const uint64_t waitTransId) const
     140              : {
     141           13 :     InnerMessage msg;
     142           13 :     msg.msgType = InnerMsgType::INNER_MSG_PUSH;
     143              :     do {
     144           14 :         if (entity.IsDataPeeked()) {
     145              :             // if match, return
     146            4 :             if (Match(entity, waitTransId, false)) {
     147            3 :                 return FsmStatus::FSM_SUCCESS;
     148              :             };
     149              :             // not match, free mbuf
     150            1 :             Mbuf * const mbuf = entity.GetMbuf();
     151            1 :             if (mbuf != nullptr) {
     152            1 :                 (void)halMbufFree(mbuf);
     153            1 :                 entity.SetMbuf(nullptr);
     154            1 :                 DGW_LOG_RUN_INFO("[FSM] Peek mbuf with transId[%lu] from entity[%s], "
     155              :                     "but wait transId is [%lu], free mbuf!",
     156              :                     entity.GetTransId(), entity.ToString().c_str(), waitTransId);
     157              :             }
     158              :         }
     159              : 
     160           11 :         DGW_LOG_DEBUG("[FSM] Entity[%s]  try to peek data.", entity.ToString().c_str());
     161           11 :         if (entity.ProcessMessage(msg) == FsmStatus::FSM_ERROR) {
     162            1 :             return FsmStatus::FSM_ERROR;
     163              :         }
     164           10 :     } while (entity.IsDataPeeked());
     165              : 
     166            9 :     return FsmStatus::FSM_FAILED;
     167              : }
     168              : 
     169            5 : bool GroupEntity::CheckTimeout(const uint64_t waitTransId) const
     170              : {
     171              :     (void)waitTransId;
     172            5 :     if (groupInfo_.timeout <= 0L) {
     173            2 :         DGW_LOG_INFO("[FSM] no need check timeout, timeoutInterval:%ld, waitTransId:%lu.",
     174              :             groupInfo_.timeout, waitTransId);
     175            2 :         return false;
     176              :     }
     177            3 :     const uint64_t currTimestamp = bqs::GetNowTime();
     178            3 :     if ((currTimestamp - groupInfo_.lastTimestamp) > static_cast<uint64_t>(groupInfo_.timeout)) {
     179            2 :         DGW_LOG_INFO("[FSM] timeout, currTimestamp:%lu, lasttimestamp:%lu, timeoutInterval:%ld, waitTransId:%lu.",
     180              :             currTimestamp, groupInfo_.lastTimestamp, groupInfo_.timeout, waitTransId);
     181            2 :         return true;
     182              :     }
     183            1 :     return false;
     184              : }
     185              : 
     186            2 : EntityPtr GroupEntity::SelectEntityWithMinTransId(const std::vector<EntityPtr> &entities) const
     187              : {
     188            2 :     EntityPtr selectedEntity = nullptr;
     189            2 :     uint64_t minTransId = UINT64_MAX;
     190            6 :     for (auto &entity : entities) {
     191            4 :         if ((entity == nullptr) || !entity->IsDataPeeked()) {
     192            2 :             continue;
     193              :         }
     194            2 :         if (minTransId >= entity->GetTransId()) {
     195            2 :             minTransId = entity->GetTransId();
     196            2 :             selectedEntity = entity;
     197              :         }
     198              :     }
     199            2 :     if (selectedEntity != nullptr) {
     200            2 :         DGW_LOG_RUN_INFO("[FSM] Group entity[%s] get minTransId[%lu].", selectedEntity->ToString().c_str(), minTransId);
     201              :     }
     202            2 :     return selectedEntity;
     203            0 : }
     204              : 
     205            8 : void GroupEntity::SelectDstEntities(const uint64_t key, std::vector<Entity*> &toPushDstEntities,
     206              :     std::vector<Entity*> &reprocessDstEntities, std::vector<Entity*> &abnormalDstEntities)
     207              : {
     208            8 :     if (groupInfo_.groupPolicy == bqs::GroupPolicy::DYNAMIC) {
     209            3 :         reprocessDstEntities.emplace_back(this);
     210            4 :         return;
     211              :     }
     212              :     // Group entity, use strategy to select dst entities
     213            5 :     Strategy *const strategy = StrategyManager::GetInstance().GetStrategy(groupInfo_.groupPolicy);
     214            5 :     if (strategy == nullptr) {
     215            1 :         DGW_LOG_ERROR("Strategy in group:%u with policy:%d is null. Please check!", id_,
     216              :             static_cast<int32_t>(groupInfo_.groupPolicy));
     217            1 :         return;
     218              :     }
     219            4 :     DGW_LOG_INFO("Get strategy:%s success.",
     220              :         StrategyManager::GetInstance().GetStrategyDesc(groupInfo_.groupPolicy).c_str());
     221            4 :     std::vector<EntityPtr> selEntities;
     222            4 :     (void) strategy->Search(id_, key, selEntities, resIndex_);
     223            7 :     for (auto selEntity : selEntities) {
     224            4 :         if (selEntity->GetCurState() == FsmState::FSM_ERROR_STATE) {
     225            1 :             abnormalDstEntities.emplace_back(this);
     226            1 :             break;
     227              :         }
     228            3 :         toPushDstEntities.emplace_back(selEntity.get());
     229            4 :     }
     230            4 : }
     231              : 
     232            4 : void GroupEntity::ReprocessInTryPush(const Entity &srcEntity, DynamicRequestPtr &dynamicRequest, uint32_t &schedCfgKey)
     233              : {
     234            4 :     if (groupInfo_.groupPolicy != bqs::GroupPolicy::DYNAMIC) {
     235            1 :         return;
     236              :     }
     237              : 
     238            3 :     if (dynamicRequest == nullptr) {
     239            3 :         dynamicRequest = std::make_shared<DynamicSchedMgr::RequestInfo>();
     240            3 :         DGW_CHECK_RET_VOID((dynamicRequest != nullptr), "Fail to alloc dynamicRequest in group:%u.", id_);
     241            3 :         dynamicRequest->src.queueLogicId = srcEntity.GetGlobalId();
     242            3 :         dynamicRequest->src.modelUuid = srcEntity.GetUuId();
     243            3 :         dynamicRequest->src.queueId = srcEntity.GetId();
     244            3 :         DynamicSchedMgr::DecisionInfo decision = {};
     245            3 :         decision.transId = srcEntity.GetTransId();
     246            3 :         decision.routeLabel = srcEntity.GetRouteLabel();
     247            3 :         dynamicRequest->decisions.emplace_back(decision);
     248              :     }
     249            3 :     DynamicSchedMgr::DstGroupInfo dstGrp = {};
     250            3 :     dstGrp.logicGroupId = GetGlobalId();
     251            3 :     dynamicRequest->dsts.emplace_back(dstGrp);
     252            3 :     schedCfgKey = GetSchedCfgKey();
     253              : }
     254              : 
     255            1 : FsmStatus GroupEntity::AbProcessInTryPush()
     256              : {
     257            1 :     return ChangeState(FsmState::FSM_ERROR_STATE);
     258              : }
     259              : 
     260            1 : FsmStatus GroupEntity::PauseSubscribe(const Entity &fullEntity)
     261              : {
     262            1 :     const auto entities = EntityManager::Instance(resIndex_).GetEntitiesInGroup(id_);
     263            3 :     for (auto &entity : entities) {
     264            2 :         entity->PauseSubscribe(fullEntity);
     265              :     }
     266            1 :     return FsmStatus::FSM_SUCCESS;
     267            1 : }
     268              : 
     269            1 : FsmStatus GroupEntity::ResumeSubscribe(const Entity &notFullEntity)
     270              : {
     271            1 :     const auto entities = EntityManager::Instance(resIndex_).GetEntitiesInGroup(id_);
     272            3 :     for (auto &entity : entities) {
     273            2 :         (void) entity->ResumeSubscribe(notFullEntity);
     274              :     }
     275            1 :     return FsmStatus::FSM_SUCCESS;
     276            1 : }
     277              : 
     278            2 : FsmStatus GroupEntity::ClearQueue()
     279              : {
     280            2 :     DGW_LOG_INFO("Entity[%s] clear queue", entityDesc_.c_str());
     281            2 :     const auto entities = EntityManager::Instance(resIndex_).GetEntitiesInGroup(id_);
     282            4 :     for (auto &entity : entities) {
     283            3 :         const auto ret = entity->ClearQueue();
     284            3 :         if (ret != FsmStatus::FSM_SUCCESS) {
     285            1 :             return ret;
     286              :         }
     287              :     }
     288            1 :     groupInfo_.lastTransId = 0U;
     289            1 :     return FsmStatus::FSM_SUCCESS;
     290            2 : }
     291              : 
     292            1 : FsmStatus GroupEntity::MakeSureOutputCompletion()
     293              : {
     294            1 :     DGW_LOG_INFO("Entity[%s] MakeSureOutputCompletion", entityDesc_.c_str());
     295            1 :     FsmStatus ret = FsmStatus::FSM_SUCCESS;
     296            1 :     const auto entities = EntityManager::Instance(resIndex_).GetEntitiesInGroup(id_);
     297            2 :     for (auto &entity : entities) {
     298            2 :         ret = entity->MakeSureOutputCompletion();
     299            2 :         if (ret != FsmStatus::FSM_SUCCESS) {
     300            1 :             break;
     301              :         }
     302              :     }
     303            1 :     DGW_LOG_INFO("Entity[%s] Finish MakeSureOutputCompletion, ret is %d", entityDesc_.c_str(),
     304              :         static_cast<int32_t>(ret));
     305            1 :     return ret;
     306            1 : }
     307              : 
     308           10 : void GroupEntity::SetGroupInfo(const uint64_t lastTransId, const uint64_t lastTimestamp)
     309              : {
     310           10 :     groupInfo_.lastTransId = lastTransId;
     311           10 :     groupInfo_.lastTimestamp = lastTimestamp;
     312           10 : }
     313              : 
     314            2 : uint32_t GroupEntity::GetMbufDeviceId() const
     315              : {
     316            2 :     return mbufDeviceId_;
     317              : }
     318              : 
     319            2 : uint32_t GroupEntity::GetMbufQueueType() const
     320              : {
     321            2 :     return mbufQueueType_;
     322              : }
     323              : 
     324              : }
        

Generated by: LCOV version 2.0-1