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,
104 : SOCKET_MAX_DATA_SIZE - (uint32_t)sizeof(UtraceMsg), &pos) != 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 (!UtraceIsSocketFdValid()) {
117 3 : int32_t fd = UtraceCreateSocket(TraceAttrGetGlobalDevId());
118 3 : if (fd != TRACE_FAILURE) {
119 3 : UtraceSetSocketFd(fd);
120 : } else {
121 0 : ADIAG_SAFE_FREE(buffer);
122 0 : ADIAG_ERR("create socket failed, objName = %s, device id = %d.", objName, TraceAttrGetGlobalDevId());
123 0 : return;
124 : }
125 : }
126 6 : if (TraceRecorderWrite(UtraceGetSocketFd(), (char *)buffer, (uint32_t)sizeof(UtraceMsg) + pos) != TRACE_SUCCESS) {
127 1 : ADIAG_SAFE_FREE(buffer);
128 1 : ADIAG_ERR("write trace data to socket failed, objName = %s. strerror %s.",
129 : objName, strerror(AdiagGetErrorCode()));
130 1 : return;
131 : }
132 5 : ADIAG_SAFE_FREE(buffer);
133 5 : ADIAG_INF("write trace data to socket successfully, objName = %s.", objName);
134 5 : return;
135 : }
136 :
137 7 : STATIC TraStatus TracerGetTraceCtrl(const struct RbLog *rb, char *data, uint32_t len, uint32_t *dataPos)
138 : {
139 7 : TraceCtrlHead traceCtrl = { 0 };
140 7 : traceCtrl.magic = TRACE_MAGIC;
141 7 : traceCtrl.version = TRACE_VERSION;
142 7 : traceCtrl.pos = TRACE_POS_DEVICE;
143 7 : traceCtrl.traceType = TRACE_TYPE_BIN;
144 7 : traceCtrl.dataSize = rb->head.msgSize * TracerRbLogGetMsgNum(rb);
145 7 : traceCtrl.realTime = rb->head.realTime;
146 7 : traceCtrl.minutesWest = rb->head.minutesWest;
147 7 : traceCtrl.cpuFreq = rb->head.cpuFreq;
148 7 : traceCtrl.structSize = (uint32_t)sizeof(TraceStructSegmentHead);
149 77 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
150 70 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList *)rb->entry[i].list)->list))) {
151 63 : continue;
152 : }
153 7 : traceCtrl.structSize += (uint32_t)sizeof(TraceStructHead) +
154 7 : ((struct AdiagList *)rb->entry[i].list)->cnt * (uint32_t)sizeof(TraceStructField);
155 : }
156 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char *)&traceCtrl, sizeof(TraceCtrlHead)) != EOK) {
157 0 : ADIAG_ERR("memcpy log ctrl failed, strerr=%s.", strerror(AdiagGetErrorCode()));
158 0 : return TRACE_FAILURE;
159 : }
160 7 : *dataPos += (uint32_t)sizeof(TraceCtrlHead);
161 7 : return TRACE_SUCCESS;
162 : }
163 :
164 7 : STATIC TraStatus TracerScheduleSaveStructSegment(const struct RbLog *rb, char *data, uint32_t len, uint32_t *dataPos)
165 : {
166 7 : TraceStructSegmentHead structSegmentHead = { 0 };
167 77 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
168 70 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList *)rb->entry[i].list)->list))) {
169 63 : continue;
170 : }
171 7 : structSegmentHead.structCount++;
172 : }
173 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char *)&structSegmentHead, sizeof(TraceStructSegmentHead)) != EOK) {
174 0 : ADIAG_ERR("memcpy struct segment head failed, strerr=%s.", strerror(AdiagGetErrorCode()));
175 0 : return TRACE_FAILURE;
176 : }
177 7 : *dataPos += (uint32_t)sizeof(TraceStructSegmentHead);
178 :
179 77 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
180 70 : struct AdiagList *traList = (struct AdiagList *)(rb->entry[i].list);
181 70 : if ((traList == NULL) || (ListEmpty(&traList->list))) {
182 63 : continue;
183 : }
184 7 : TraceStructHead structHead = { 0 };
185 7 : structHead.structType = i;
186 7 : structHead.itemNum = ((struct AdiagList *)rb->entry[i].list)->cnt;
187 7 : errno_t err = strcpy_s(structHead.structName, TRACE_NAME_LENGTH, rb->entry[i].name);
188 7 : if (err != EOK) {
189 0 : ADIAG_ERR("copy struct name failed, struct name=%s.", rb->entry[i].name);
190 : }
191 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char *)&structHead, sizeof(TraceStructHead)) != EOK) {
192 0 : ADIAG_ERR("memcpy struct head failed, entry name=%s, struct name=%s, strerr=%s.",
193 : rb->entry[i].name, structHead.structName, strerror(AdiagGetErrorCode()));
194 0 : continue;
195 : }
196 7 : *dataPos += (uint32_t)sizeof(TraceStructHead);
197 :
198 7 : struct AdiagListNode *node = NULL;
199 7 : struct ListHead *pos = NULL;
200 :
201 69 : LIST_FOR_EACH(pos, &traList->list) {
202 62 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
203 124 : if ((node == NULL) ||
204 62 : (memcpy_s(data + *dataPos, len - *dataPos, node->data, sizeof(TraceStructField)) != EOK)) {
205 0 : ADIAG_ERR("get trace struct field failed, struct name=%s, strerr=%s.",
206 : rb->entry[i].name, strerror(AdiagGetErrorCode()));
207 0 : return TRACE_FAILURE;
208 : }
209 62 : *dataPos += (uint32_t)sizeof(TraceStructField);
210 : }
211 : }
212 7 : return TRACE_SUCCESS;
213 : }
214 :
215 7 : STATIC TraStatus TracerScheduleSaveDataHead(const struct RbLog *rb, char *data, uint32_t len, uint32_t *dataPos)
216 : {
217 7 : TraceStructDataHead dataHead = { 0 };
218 7 : dataHead.msgSize = rb->head.msgSize;
219 7 : dataHead.msgTxtSize = rb->head.msgTxtSize;
220 7 : dataHead.msgNum = TracerRbLogGetMsgNum(rb);
221 7 : if (memcpy_s(data + *dataPos, len - *dataPos, (char *)&dataHead, sizeof(TraceStructDataHead)) != EOK) {
222 0 : ADIAG_ERR("memcpy data head failed, strerr=%s.", strerror(AdiagGetErrorCode()));
223 0 : return TRACE_FAILURE;
224 : }
225 7 : *dataPos += (uint32_t)sizeof(TraceStructDataHead);
226 7 : return TRACE_SUCCESS;
227 : }
228 :
229 7 : STATIC TraStatus TracerGetDataStruct(const struct RbLog *newRb, char *data, uint32_t len, uint32_t *dataPos)
230 : {
231 7 : if (TracerGetTraceCtrl(newRb, data, len, dataPos) != TRACE_SUCCESS) {
232 0 : ADIAG_ERR("get log ctrl failed.");
233 0 : return TRACE_FAILURE;
234 : }
235 :
236 7 : if (TracerScheduleSaveStructSegment(newRb, data, len, dataPos) != TRACE_SUCCESS) {
237 0 : ADIAG_ERR("write struct segment failed.");
238 0 : return TRACE_FAILURE;
239 : }
240 :
241 7 : if (TracerScheduleSaveDataHead(newRb, data, len, dataPos) != TRACE_SUCCESS) {
242 0 : ADIAG_ERR("write data head failed.");
243 0 : return TRACE_FAILURE;
244 : }
245 7 : return TRACE_SUCCESS;
246 : }
247 :
248 7 : STATIC TraStatus TracerGetOriMsgData(struct RbLog *newRb, char *data, uint32_t len, uint32_t *dataPos)
249 : {
250 7 : if (TracerGetDataStruct(newRb, data, len, dataPos) != TRACE_SUCCESS) {
251 0 : ADIAG_ERR("get data struct failed.");
252 0 : return TRACE_FAILURE;
253 : }
254 :
255 7 : char *txt = NULL;
256 7 : uint32_t txtLen = 0;
257 7 : TraStatus ret = TRACE_SUCCESS;
258 7 : uint32_t dataLen = *dataPos;
259 : do {
260 67 : ret = TraceRbLogReadOriRbMsg(newRb, &txt, &txtLen);
261 67 : if (ret == TRACE_RING_BUFFER_EMPTY) {
262 7 : break;
263 : }
264 60 : if (ret != TRACE_SUCCESS) {
265 0 : break;
266 : }
267 60 : if (memcpy_s(data + dataLen, len - dataLen, txt, txtLen) != EOK) {
268 0 : continue;
269 : }
270 60 : dataLen += txtLen;
271 60 : } while (ret == TRACE_SUCCESS);
272 : // if data is null, clear dataPos
273 7 : *dataPos = (*dataPos == dataLen) ? 0 : dataLen;
274 7 : return TRACE_SUCCESS;
275 : }
276 :
277 : /**
278 : * @brief save msg to file with binary file
279 : * @param [in] newRb: ringbuffer
280 : * @param [in] timeStr: time stamp of file name
281 : * @param [in] objName: object name
282 : * @return NA
283 : */
284 7 : void TracerScheduleSaveObjBinData(struct RbLog *newRb, const char *timeStr, const char *eventName, const char *objName)
285 : {
286 : (void)eventName;
287 7 : if (TraceAttrGetSaveMode() != 1) {
288 0 : return;
289 : }
290 7 : UtraceMsg *buffer = (UtraceMsg *)AdiagMalloc(SOCKET_MAX_DATA_SIZE);
291 7 : if (buffer == NULL) {
292 0 : ADIAG_ERR("malloc for send msg to utrace server failed, strerr = %s.", strerror(AdiagGetErrorCode()));
293 0 : return;
294 : }
295 :
296 7 : if (TracerGetMsgHead(buffer, FILE_SAVE_MODE_BIN, objName, timeStr) != TRACE_SUCCESS) {
297 0 : ADIAG_SAFE_FREE(buffer);
298 0 : ADIAG_ERR("get timestamp failed, objName = %s.", objName);
299 0 : return;
300 : }
301 7 : uint32_t pos = 0;
302 7 : if ((TracerGetOriMsgData(newRb, buffer->data,
303 : SOCKET_MAX_DATA_SIZE - (uint32_t)sizeof(UtraceMsg), &pos) != TRACE_SUCCESS)) {
304 0 : ADIAG_SAFE_FREE(buffer);
305 0 : ADIAG_ERR("get msg data failed, objName = %s.", objName);
306 0 : return;
307 : }
308 7 : if (pos == 0) {
309 1 : ADIAG_SAFE_FREE(buffer);
310 1 : ADIAG_INF("no date need to save, objName = %s.", objName);
311 1 : return;
312 : }
313 6 : buffer->dataLength = pos;
314 :
315 6 : if (!UtraceIsSocketFdValid()) {
316 4 : int32_t fd = UtraceCreateSocket(TraceAttrGetGlobalDevId());
317 4 : if (fd != TRACE_FAILURE) {
318 2 : UtraceSetSocketFd(fd);
319 : } else {
320 2 : ADIAG_SAFE_FREE(buffer);
321 2 : ADIAG_ERR("create socket failed, objName = %s, device id = %d.", objName, TraceAttrGetGlobalDevId());
322 2 : return;
323 : }
324 : }
325 4 : if (TraceRecorderWrite(UtraceGetSocketFd(), (char *)buffer, (uint32_t)sizeof(UtraceMsg) + pos) != TRACE_SUCCESS) {
326 0 : ADIAG_SAFE_FREE(buffer);
327 0 : ADIAG_ERR("write trace data to socket failed, objName = %s.", objName);
328 0 : return;
329 : }
330 4 : ADIAG_SAFE_FREE(buffer);
331 4 : return;
332 : }
333 :
334 0 : TraStatus TracerScheduleSafeSave(Tracer *tracer, uint64_t timeStamp)
335 : {
336 : (void)tracer;
337 : (void)timeStamp;
338 0 : return TRACE_SUCCESS;
339 : }
|