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