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 : #include "tracer_mgr_operate.h"
11 : #include "tracer_mgr_operate_inner.h"
12 : #include "adiag_print.h"
13 : #include "trace_recorder.h"
14 : #include "adiag_utils.h"
15 : #include "trace_system_api.h"
16 : #include "trace_msg.h"
17 : #include "utrace_socket.h"
18 : #include "trace_attr.h"
19 :
20 : #define SOCKET_MAX_DATA_SIZE 524288
21 :
22 15 : STATIC TraStatus TracerGetMsgHead(UtraceMsg* traceHead, uint8_t saveType, const char* objName, const char* timeStr)
23 : {
24 15 : traceHead->magic = UTRACE_HEAD_MAGIC;
25 15 : traceHead->version = UTRACE_HEAD_VERSION;
26 15 : traceHead->hostPid = TraceAttrGetGlobalPid();
27 15 : traceHead->devicePid = TraceAttrGetPid();
28 15 : traceHead->deviceId = TraceAttrGetGlobalDevId();
29 15 : traceHead->tracerType = TRACER_TYPE_SCHEDULE;
30 15 : traceHead->saveType = saveType;
31 :
32 15 : errno_t err = strcpy_s(traceHead->objName, TRACE_NAME_LENGTH, objName);
33 15 : if (err != EOK) {
34 0 : ADIAG_ERR("strcpy objName failed, result=%d, strerr=%s.", (int32_t)err, strerror(AdiagGetErrorCode()));
35 0 : return TRACE_FAILURE;
36 : }
37 15 : err = strcpy_s(traceHead->eventTime, TIMESTAMP_MAX_LENGTH, timeStr);
38 15 : if (err != EOK) {
39 0 : ADIAG_ERR("strcpy eventTime failed, result=%d, strerr=%s.", (int32_t)err, strerror(AdiagGetErrorCode()));
40 0 : return TRACE_FAILURE;
41 : }
42 15 : return TRACE_SUCCESS;
43 : }
44 :
45 8 : STATIC TraStatus TracerGetMsgData(struct RbLog* newRb, char* data, uint32_t len, uint32_t* dataPos)
46 : {
47 8 : char* txt = NULL;
48 8 : TraStatus ret = TRACE_SUCCESS;
49 8 : char timestamp[TIMESTAMP_MAX_LENGTH] = {0};
50 : do {
51 14 : ret = TraceRbLogReadRbMsg(newRb, (char*)×tamp, TIMESTAMP_MAX_LENGTH, &txt);
52 14 : if (ret == TRACE_RING_BUFFER_EMPTY) {
53 8 : break;
54 : }
55 6 : if (ret != TRACE_SUCCESS) {
56 0 : break;
57 : }
58 6 : if (memcpy_s(data + *dataPos, len - *dataPos, timestamp, (uint32_t)strlen(timestamp)) != EOK) {
59 0 : continue;
60 : }
61 6 : *dataPos += (uint32_t)strlen(timestamp);
62 6 : uint32_t txtLen = (uint32_t)strlen(txt);
63 6 : if (memcpy_s(data + *dataPos, len - *dataPos, txt, txtLen) != EOK) {
64 0 : continue;
65 : }
66 6 : *dataPos += txtLen;
67 6 : if ((txtLen > 0) && (txt[txtLen - 1U] != '\n')) {
68 6 : if (memcpy_s(data + *dataPos, len - *dataPos, "\n", 1) != EOK) {
69 0 : continue;
70 : }
71 6 : *dataPos += 1U;
72 : }
73 6 : } while (ret == TRACE_SUCCESS);
74 8 : return TRACE_SUCCESS;
75 : }
76 :
77 : /**
78 : * @brief save msg to file with txt file
79 : * @param [in] newRb: ringbuffer
80 : * @param [in] timeStr: time stamp of file name
81 : * @param [in] objName: object name
82 : * @return NA
83 : */
84 8 : void TracerScheduleSaveObjData(struct RbLog* newRb, const char* timeStr, const char* eventName, const char* objName)
85 : {
86 : (void)eventName;
87 8 : if (TraceAttrGetSaveMode() != 1) {
88 0 : return;
89 : }
90 8 : UtraceMsg* buffer = (UtraceMsg*)AdiagMalloc(SOCKET_MAX_DATA_SIZE);
91 8 : if (buffer == NULL) {
92 0 : ADIAG_ERR("malloc for send msg to utrace server failed, strerr = %s.", strerror(AdiagGetErrorCode()));
93 0 : return;
94 : }
95 :
96 8 : if (TracerGetMsgHead(buffer, FILE_SAVE_MODE_CHAR, objName, timeStr) != TRACE_SUCCESS) {
97 0 : ADIAG_SAFE_FREE(buffer);
98 0 : ADIAG_ERR("get timestamp failed, objName = %s.", objName);
99 0 : return;
100 : }
101 :
102 8 : uint32_t pos = 0;
103 8 : if ((TracerGetMsgData(newRb, buffer->data, SOCKET_MAX_DATA_SIZE - (uint32_t)sizeof(UtraceMsg), &pos) !=
104 : TRACE_SUCCESS)) {
105 0 : ADIAG_SAFE_FREE(buffer);
106 0 : ADIAG_ERR("get msg data failed, objName = %s.", objName);
107 0 : return;
108 : }
109 8 : if (pos == 0) {
110 2 : ADIAG_SAFE_FREE(buffer);
111 2 : ADIAG_INF("no date need to save, objName = %s.", objName);
112 2 : return;
113 : }
114 6 : buffer->dataLength = pos;
115 :
116 6 : if (UtraceWriteSocket(TraceAttrGetGlobalDevId(), (char*)buffer, (uint32_t)sizeof(UtraceMsg) + pos) !=
117 : TRACE_SUCCESS) {
118 1 : ADIAG_SAFE_FREE(buffer);
119 1 : ADIAG_ERR(
120 : "write trace data to socket failed, objName = %s. strerror %s.", objName, strerror(AdiagGetErrorCode()));
121 1 : return;
122 : }
123 5 : ADIAG_SAFE_FREE(buffer);
124 5 : ADIAG_INF("write trace data to socket successfully, objName = %s.", objName);
125 5 : return;
126 : }
127 :
128 7 : STATIC TraStatus TracerGetTraceCtrl(const struct RbLog* rb, char* data, uint32_t len, uint32_t* dataPos)
129 : {
130 7 : TraceCtrlHead traceCtrl = {0};
131 7 : traceCtrl.magic = TRACE_MAGIC;
132 7 : traceCtrl.version = TRACE_VERSION;
133 7 : traceCtrl.pos = TRACE_POS_DEVICE;
134 7 : traceCtrl.traceType = TRACE_TYPE_BIN;
135 7 : traceCtrl.dataSize = rb->head.msgSize * TracerRbLogGetMsgNum(rb);
136 7 : traceCtrl.realTime = rb->head.realTime;
137 7 : traceCtrl.minutesWest = rb->head.minutesWest;
138 7 : traceCtrl.cpuFreq = rb->head.cpuFreq;
139 7 : traceCtrl.structSize = (uint32_t)sizeof(TraceStructSegmentHead);
140 77 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
141 70 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList*)rb->entry[i].list)->list))) {
142 63 : continue;
143 : }
144 7 : traceCtrl.structSize += (uint32_t)sizeof(TraceStructHead) +
145 7 : ((struct AdiagList*)rb->entry[i].list)->cnt * (uint32_t)sizeof(TraceStructField);
146 : }
147 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char*)&traceCtrl, sizeof(TraceCtrlHead)) != EOK) {
148 0 : ADIAG_ERR("memcpy log ctrl failed, strerr=%s.", strerror(AdiagGetErrorCode()));
149 0 : return TRACE_FAILURE;
150 : }
151 7 : *dataPos += (uint32_t)sizeof(TraceCtrlHead);
152 7 : return TRACE_SUCCESS;
153 : }
154 :
155 7 : STATIC TraStatus TracerScheduleSaveStructSegment(const struct RbLog* rb, char* data, uint32_t len, uint32_t* dataPos)
156 : {
157 7 : TraceStructSegmentHead structSegmentHead = {0};
158 77 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
159 70 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList*)rb->entry[i].list)->list))) {
160 63 : continue;
161 : }
162 7 : structSegmentHead.structCount++;
163 : }
164 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char*)&structSegmentHead, sizeof(TraceStructSegmentHead)) != EOK) {
165 0 : ADIAG_ERR("memcpy struct segment head failed, strerr=%s.", strerror(AdiagGetErrorCode()));
166 0 : return TRACE_FAILURE;
167 : }
168 7 : *dataPos += (uint32_t)sizeof(TraceStructSegmentHead);
169 :
170 77 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
171 70 : struct AdiagList* traList = (struct AdiagList*)(rb->entry[i].list);
172 70 : if ((traList == NULL) || (ListEmpty(&traList->list))) {
173 63 : continue;
174 : }
175 7 : TraceStructHead structHead = {0};
176 7 : structHead.structType = (uint8_t)i;
177 7 : structHead.itemNum = ((struct AdiagList*)rb->entry[i].list)->cnt;
178 7 : errno_t err = strcpy_s(structHead.structName, TRACE_NAME_LENGTH, rb->entry[i].name);
179 7 : if (err != EOK) {
180 0 : ADIAG_ERR("copy struct name failed, struct name=%s.", rb->entry[i].name);
181 : }
182 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char*)&structHead, sizeof(TraceStructHead)) != EOK) {
183 0 : ADIAG_ERR(
184 : "memcpy struct head failed, entry name=%s, struct name=%s, strerr=%s.", rb->entry[i].name,
185 : structHead.structName, strerror(AdiagGetErrorCode()));
186 0 : continue;
187 : }
188 7 : *dataPos += (uint32_t)sizeof(TraceStructHead);
189 :
190 7 : struct AdiagListNode* node = NULL;
191 7 : struct ListHead* pos = NULL;
192 :
193 69 : LIST_FOR_EACH(pos, &traList->list)
194 : {
195 62 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
196 124 : if ((node == NULL) ||
197 62 : (memcpy_s(data + *dataPos, len - *dataPos, node->data, sizeof(TraceStructField)) != EOK)) {
198 0 : ADIAG_ERR(
199 : "get trace struct field failed, struct name=%s, strerr=%s.", rb->entry[i].name,
200 : strerror(AdiagGetErrorCode()));
201 0 : return TRACE_FAILURE;
202 : }
203 62 : *dataPos += (uint32_t)sizeof(TraceStructField);
204 : }
205 : }
206 7 : return TRACE_SUCCESS;
207 : }
208 :
209 7 : STATIC TraStatus TracerScheduleSaveDataHead(const struct RbLog* rb, char* data, uint32_t len, uint32_t* dataPos)
210 : {
211 7 : TraceStructDataHead dataHead = {0};
212 7 : dataHead.msgSize = rb->head.msgSize;
213 7 : dataHead.msgTxtSize = rb->head.msgTxtSize;
214 7 : dataHead.msgNum = TracerRbLogGetMsgNum(rb);
215 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char*)&dataHead, sizeof(TraceStructDataHead)) != EOK) {
216 0 : ADIAG_ERR("memcpy data head failed, strerr=%s.", strerror(AdiagGetErrorCode()));
217 0 : return TRACE_FAILURE;
218 : }
219 7 : *dataPos += (uint32_t)sizeof(TraceStructDataHead);
220 7 : return TRACE_SUCCESS;
221 : }
222 :
223 7 : STATIC TraStatus TracerGetDataStruct(const struct RbLog* newRb, char* data, uint32_t len, uint32_t* dataPos)
224 : {
225 7 : if (TracerGetTraceCtrl(newRb, data, len, dataPos) != TRACE_SUCCESS) {
226 0 : ADIAG_ERR("get log ctrl failed.");
227 0 : return TRACE_FAILURE;
228 : }
229 :
230 7 : if (TracerScheduleSaveStructSegment(newRb, data, len, dataPos) != TRACE_SUCCESS) {
231 0 : ADIAG_ERR("write struct segment failed.");
232 0 : return TRACE_FAILURE;
233 : }
234 :
235 7 : if (TracerScheduleSaveDataHead(newRb, data, len, dataPos) != TRACE_SUCCESS) {
236 0 : ADIAG_ERR("write data head failed.");
237 0 : return TRACE_FAILURE;
238 : }
239 7 : return TRACE_SUCCESS;
240 : }
241 :
242 7 : STATIC TraStatus TracerGetOriMsgData(struct RbLog* newRb, char* data, uint32_t len, uint32_t* dataPos)
243 : {
244 7 : if (TracerGetDataStruct(newRb, data, len, dataPos) != TRACE_SUCCESS) {
245 0 : ADIAG_ERR("get data struct failed.");
246 0 : return TRACE_FAILURE;
247 : }
248 :
249 7 : char* txt = NULL;
250 7 : uint32_t txtLen = 0;
251 7 : TraStatus ret = TRACE_SUCCESS;
252 7 : uint32_t dataLen = *dataPos;
253 : do {
254 67 : ret = TraceRbLogReadOriRbMsg(newRb, &txt, &txtLen);
255 67 : if (ret == TRACE_RING_BUFFER_EMPTY) {
256 7 : break;
257 : }
258 60 : if (ret != TRACE_SUCCESS) {
259 0 : break;
260 : }
261 60 : if (memcpy_s(data + dataLen, len - dataLen, txt, txtLen) != EOK) {
262 0 : continue;
263 : }
264 60 : dataLen += txtLen;
265 60 : } while (ret == TRACE_SUCCESS);
266 : // if data is null, clear dataPos
267 7 : *dataPos = (*dataPos == dataLen) ? 0 : dataLen;
268 7 : return TRACE_SUCCESS;
269 : }
270 :
271 : /**
272 : * @brief save msg to file with binary file
273 : * @param [in] newRb: ringbuffer
274 : * @param [in] timeStr: time stamp of file name
275 : * @param [in] objName: object name
276 : * @return NA
277 : */
278 7 : void TracerScheduleSaveObjBinData(struct RbLog* newRb, const char* timeStr, const char* eventName, const char* objName)
279 : {
280 : (void)eventName;
281 7 : if (TraceAttrGetSaveMode() != 1) {
282 0 : return;
283 : }
284 7 : UtraceMsg* buffer = (UtraceMsg*)AdiagMalloc(SOCKET_MAX_DATA_SIZE);
285 7 : if (buffer == NULL) {
286 0 : ADIAG_ERR("malloc for send msg to utrace server failed, strerr = %s.", strerror(AdiagGetErrorCode()));
287 0 : return;
288 : }
289 :
290 7 : if (TracerGetMsgHead(buffer, FILE_SAVE_MODE_BIN, objName, timeStr) != TRACE_SUCCESS) {
291 0 : ADIAG_SAFE_FREE(buffer);
292 0 : ADIAG_ERR("get timestamp failed, objName = %s.", objName);
293 0 : return;
294 : }
295 7 : uint32_t pos = 0;
296 7 : if ((TracerGetOriMsgData(newRb, buffer->data, SOCKET_MAX_DATA_SIZE - (uint32_t)sizeof(UtraceMsg), &pos) !=
297 : TRACE_SUCCESS)) {
298 0 : ADIAG_SAFE_FREE(buffer);
299 0 : ADIAG_ERR("get msg data failed, objName = %s.", objName);
300 0 : return;
301 : }
302 7 : if (pos == 0) {
303 1 : ADIAG_SAFE_FREE(buffer);
304 1 : ADIAG_INF("no date need to save, objName = %s.", objName);
305 1 : return;
306 : }
307 6 : buffer->dataLength = pos;
308 :
309 6 : if (UtraceWriteSocket(TraceAttrGetGlobalDevId(), (char*)buffer, (uint32_t)sizeof(UtraceMsg) + pos) !=
310 : TRACE_SUCCESS) {
311 2 : ADIAG_SAFE_FREE(buffer);
312 2 : ADIAG_ERR("write trace data to socket failed, objName = %s.", objName);
313 2 : return;
314 : }
315 4 : ADIAG_SAFE_FREE(buffer);
316 4 : return;
317 : }
318 :
319 0 : TraStatus TracerScheduleSafeSave(Tracer* tracer, uint64_t timeStamp)
320 : {
321 : (void)tracer;
322 : (void)timeStamp;
323 0 : return TRACE_SUCCESS;
324 : }
|