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 "adx_dump_receive.h"
12 : #include <algorithm>
13 : #include "mmpa_api.h"
14 : #include "memory_utils.h"
15 : #include "adx_dump_record.h"
16 : #include "log/adx_log.h"
17 : namespace Adx {
18 6 : int32_t AdxDumpReceive::Init()
19 : {
20 6 : init_ = true;
21 6 : return IDE_DAEMON_OK;
22 : }
23 :
24 14 : int32_t AdxDumpReceive::Process(const CommHandle &handle, const SharedPtr<MsgProto> &proto)
25 : {
26 : // hand shake control(sent by IdeDumpStart)
27 14 : if (proto->msgType == MsgType::MSG_CTRL && proto->status == MsgStatus::MSG_STATUS_HAND_SHAKE) {
28 36 : IdeErrorT err = AdxMsgProto::SendResponse(handle,
29 12 : (CmdClassT)proto->reqType, proto->devId, MsgStatus::MSG_STATUS_NONE_ERROR);
30 12 : if (err != IDE_DAEMON_NONE_ERROR) {
31 1 : IDE_LOGE("send dump handshake response failed! device(id:%u,session:%zu), err: %d",
32 : proto->devId, handle.session, err);
33 1 : return err;
34 : }
35 : } else {
36 2 : IDE_LOGW("receive invalid ctrl msg! device(id:%u,session:%zu), type: %d, status: %d",
37 : proto->devId, handle.session, proto->msgType, proto->status);
38 2 : return IDE_DAEMON_OK;
39 : }
40 : // store client session(persistent session. must be closed before close server)
41 11 : AdxCommHandle adxHandle = const_cast<AdxCommHandle>(&handle);
42 11 : StoreSession(proto->devId, adxHandle);
43 : // read dump data(sent by IdeDumpData) and end dump control(sent by IdeDumpEnd)
44 11 : int32_t ret = Receive(handle, proto);
45 11 : ReleaseSession(proto->devId, adxHandle);
46 11 : return ret;
47 : }
48 :
49 11 : int32_t AdxDumpReceive::Receive(const CommHandle &handle, const SharedPtr<MsgProto> &proto)
50 : {
51 11 : int32_t length = 0;
52 11 : uint32_t protoHeaderLen = static_cast<uint32_t>(sizeof(MsgProto));
53 11 : uint32_t chunkHeaderLen = static_cast<uint32_t>(sizeof(DumpChunk));
54 11 : MsgProto *msg = nullptr;
55 14 : while (init_) {
56 13 : IDE_LOGI("receiving new dump data from device(id:%u,session:%zu)", proto->devId, handle.session);
57 13 : int ret = AdxCommOptManager::Instance().Read(handle, (IdeRecvBuffT)&msg, length, COMM_OPT_BLOCK);
58 22 : IDE_CTRL_VALUE_WARN(ret == IDE_DAEMON_OK, return ret,
59 : "read dump data error. device(id:%u,session:%zu), err:%d", proto->devId, handle.session, ret);
60 12 : IDE_CTRL_VALUE_WARN(msg != nullptr && length >= 0, { IdeXfree(msg); return IDE_DAEMON_ERROR; },
61 : "dump data is invalid. device(id:%u,session:%zu)", proto->devId, handle.session);
62 :
63 11 : uint32_t protoEntryLen = static_cast<uint32_t>(length);
64 11 : IDE_CTRL_VALUE_WARN(protoEntryLen >= protoHeaderLen, { IdeXfree(msg); return IDE_DAEMON_ERROR; },
65 : "recvLen(%u) too small for MsgProto header(%u bytes)", protoEntryLen, protoHeaderLen);
66 :
67 10 : SharedPtr<MsgProto> msgPtr(msg, IdeXfree);
68 10 : msg = nullptr;
69 10 : if (msgPtr->msgType == MsgType::MSG_CTRL) {
70 4 : if (msgPtr->status == MsgStatus::MSG_STATUS_DATA_END) {
71 3 : IDE_LOGI("received dump ctrl msg from device(id:%u,session:%zu), end transfer dump data",
72 : proto->devId, handle.session);
73 3 : return IDE_DAEMON_OK;
74 : } else {
75 1 : continue;
76 : }
77 : }
78 6 : uint32_t protoDataLen = protoEntryLen - protoHeaderLen;
79 6 : IDE_CTRL_VALUE_WARN(msgPtr->sliceLen == protoDataLen, return IDE_DAEMON_ERROR,
80 : "msg sliceLen(%u) not equal actual msg data buffer size(%u)", msgPtr->sliceLen, protoDataLen);
81 :
82 5 : IDE_CTRL_VALUE_WARN(protoDataLen >= chunkHeaderLen, return IDE_DAEMON_ERROR,
83 : "msg dataLen(%u) too small for DumpChunk header(%u)", protoDataLen, chunkHeaderLen);
84 :
85 4 : DumpChunk* dumpChunk = reinterpret_cast<DumpChunk*>(msgPtr->data);
86 4 : uint32_t chunkDataLen = protoDataLen - chunkHeaderLen;
87 4 : IDE_CTRL_VALUE_WARN(dumpChunk->bufLen <= chunkDataLen, return IDE_DAEMON_ERROR,
88 : "chunk bufLen(%u) exceeds actual chunk data buffer size(%u)", dumpChunk->bufLen, chunkDataLen);
89 :
90 3 : IDE_LOGI("fileName: %s, bufLen: %u, isLastChunk: %u, offset: %ld, flag: %d",
91 : dumpChunk->fileName, dumpChunk->bufLen, dumpChunk->isLastChunk, dumpChunk->offset, dumpChunk->flag);
92 :
93 3 : HostDumpDataInfo data = {msgPtr, protoDataLen};
94 3 : MsgStatus status = MsgStatus::MSG_STATUS_NONE_ERROR;
95 3 : if (!AdxDumpRecord::Instance().RecordDumpDataToQueue(data)) {
96 1 : status = MsgStatus::MSG_STATUS_CACHE_FULL_ERROR;
97 : }
98 :
99 : // send respone msg to device
100 3 : IdeErrorT err = AdxMsgProto::SendResponse(handle, proto->reqType, proto->devId, status);
101 3 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_NONE_ERROR, return IDE_DAEMON_ERROR,
102 : "send dump handshake response failed! device(id:%u,session:%zu), err: %d",
103 : proto->devId, handle.session, err);
104 11 : }
105 1 : return IDE_DAEMON_OK;
106 : }
107 :
108 7 : int32_t AdxDumpReceive::UnInit()
109 : {
110 7 : init_ = false;
111 7 : return IDE_DAEMON_OK;
112 : }
113 :
114 12 : void AdxDumpReceive::StoreSession(uint32_t deviceId, AdxCommHandle handle)
115 : {
116 12 : if (handle != nullptr) {
117 12 : std::lock_guard<std::mutex> lock {mutex_};
118 12 : handles_[deviceId].push_back(handle);
119 12 : }
120 12 : }
121 :
122 11 : void AdxDumpReceive::ReleaseSession(uint32_t deviceId, AdxCommHandle handle)
123 : {
124 11 : if (handle != nullptr) {
125 11 : std::lock_guard<std::mutex> lock {mutex_};
126 11 : auto map_it = handles_.find(deviceId);
127 11 : if (map_it != handles_.end()) {
128 11 : auto& vec = map_it->second;
129 11 : auto vec_it = std::find(vec.begin(), vec.end(), handle);
130 11 : if (vec_it != vec.end()) {
131 11 : vec.erase(vec_it);
132 : }
133 : }
134 11 : }
135 11 : }
136 :
137 4 : int32_t AdxDumpReceive::Terminate()
138 : {
139 4 : std::lock_guard<std::mutex> lock {mutex_};
140 5 : for (auto& map_it: handles_) {
141 2 : for (auto& handle : map_it.second) {
142 1 : IDE_LOGW("close alive client session. device: %u, session: %zu", map_it.first, handle->session);
143 1 : (void)AdxCommOptManager::Instance().Close(*handle);
144 : }
145 : }
146 4 : handles_.clear();
147 4 : return IDE_DAEMON_OK;
148 4 : }
149 : }
|