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 "adiag_utils.h"
14 : #include "trace_recorder.h"
15 : #include "trace_system_api.h"
16 : /**
17 : * @brief save msg to file with txt file
18 : * @param [in] newRb: ringbuffer
19 : * @param [in] timeStr: time stamp of file name
20 : * @param [in] objName: object name
21 : * @return NA
22 : */
23 329 : void TracerScheduleSaveObjData(struct RbLog *newRb, const char *timeStr, const char *eventName, const char *objName)
24 : {
25 329 : TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, objName, TRACE_FILE_TXT_SUFFIX };
26 329 : TraceDirInfo dirInfo = { eventName, TraceGetPid(), timeStr, false };
27 329 : int32_t fd = -1;
28 329 : char *txt = NULL;
29 329 : char timestamp[TIMESTAMP_MAX_LENGTH] = {0};
30 329 : TraStatus ret = TRACE_SUCCESS;
31 : do {
32 21030 : ret = TraceRbLogReadRbMsg(newRb, (char *)×tamp, TIMESTAMP_MAX_LENGTH, &txt);
33 21030 : if (ret == TRACE_RING_BUFFER_EMPTY) {
34 307 : break;
35 : }
36 20723 : if (ret != TRACE_SUCCESS) {
37 0 : ADIAG_ERR("read log msg failed, ret : %d", ret);
38 0 : break;
39 : }
40 :
41 20723 : if ((fd == -1) && (TraceRecorderGetFd(&dirInfo, &fileInfo, &fd) != TRACE_SUCCESS)) {
42 22 : ADIAG_ERR("get file fd failed, object name=%s.", objName);
43 22 : break;
44 : }
45 20701 : uint32_t txtLen = (uint32_t)strlen(txt);
46 20701 : (void)TraceRecorderWrite(fd, timestamp, (uint32_t)strlen(timestamp));
47 20701 : (void)TraceRecorderWrite(fd, txt, txtLen);
48 20701 : if ((txtLen > 0) && (txt[txtLen - 1U] != '\n')) {
49 20701 : (void)TraceRecorderWrite(fd, "\n", 1);
50 : }
51 20701 : } while (ret == TRACE_SUCCESS);
52 329 : TraceClose(&fd);
53 329 : }
54 :
55 21 : STATIC TraStatus TracerScheduleSaveTraceCtrl(const RbLog *rb, int32_t fd, const char *objName)
56 : {
57 21 : TraceCtrlHead traceCtrl = { 0 };
58 21 : traceCtrl.magic = TRACE_MAGIC;
59 21 : traceCtrl.version = TRACE_VERSION;
60 21 : traceCtrl.pos = TRACE_POS_HOST;
61 21 : traceCtrl.traceType = TRACE_TYPE_BIN;
62 21 : traceCtrl.dataSize = rb->head.msgSize * TracerRbLogGetMsgNum(rb);
63 21 : traceCtrl.realTime = rb->head.realTime;
64 21 : traceCtrl.minutesWest = rb->head.minutesWest;
65 21 : traceCtrl.structSize = (uint32_t)sizeof(TraceStructSegmentHead);
66 21 : traceCtrl.cpuFreq = rb->head.cpuFreq;
67 231 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
68 210 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList *)rb->entry[i].list)->list))) {
69 189 : continue;
70 : }
71 21 : traceCtrl.structSize += (uint32_t)sizeof(TraceStructHead) +
72 21 : ((struct AdiagList *)rb->entry[i].list)->cnt * (uint32_t)sizeof(TraceStructField);
73 : }
74 21 : if (TraceRecorderWrite(fd, (char *)&traceCtrl, (uint32_t)sizeof(TraceCtrlHead)) != TRACE_SUCCESS) {
75 0 : ADIAG_ERR("write log ctrl failed, object name=%s.", objName);
76 0 : return TRACE_FAILURE;
77 : }
78 21 : return TRACE_SUCCESS;
79 : }
80 :
81 21 : STATIC TraStatus TracerScheduleSaveStructSegment(const RbLog *rb, int32_t fd, const char *objName)
82 : {
83 21 : TraceStructSegmentHead structSegmentHead = { 0 };
84 231 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
85 210 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList *)rb->entry[i].list)->list))) {
86 189 : continue;
87 : }
88 21 : structSegmentHead.structCount++;
89 : }
90 21 : if (TraceRecorderWrite(fd, (char *)&structSegmentHead, (uint32_t)sizeof(TraceStructSegmentHead)) != TRACE_SUCCESS) {
91 0 : ADIAG_ERR("write struct segment head failed, object name=%s.", objName);
92 0 : return TRACE_FAILURE;
93 : }
94 :
95 231 : for (uint8_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
96 210 : struct AdiagList *traList = (struct AdiagList *)(rb->entry[i].list);
97 210 : if ((traList == NULL) || (ListEmpty(&traList->list))) {
98 189 : continue;
99 : }
100 21 : TraceStructHead structHead = { 0 };
101 21 : structHead.structType = i;
102 21 : structHead.itemNum = ((struct AdiagList *)rb->entry[i].list)->cnt;
103 21 : errno_t err = strcpy_s(structHead.structName, TRACE_NAME_LENGTH, rb->entry[i].name);
104 21 : if (err != EOK) {
105 0 : ADIAG_ERR("copy struct name failed, object name=%s, struct name=%s.", objName, rb->entry[i].name);
106 : }
107 21 : if (TraceRecorderWrite(fd, (char *)&structHead, (uint32_t)sizeof(TraceStructHead)) != TRACE_SUCCESS) {
108 0 : ADIAG_ERR("write struct head failed, entry name=%s, struct name=%s.",
109 : rb->entry[i].name, structHead.structName);
110 0 : continue;
111 : }
112 :
113 21 : struct AdiagListNode *node = NULL;
114 21 : struct ListHead *pos = NULL;
115 :
116 231 : LIST_FOR_EACH(pos, &traList->list) {
117 210 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
118 420 : if ((node == NULL) ||
119 210 : (TraceRecorderWrite(fd, node->data, (uint32_t)sizeof(TraceStructField)) != TRACE_SUCCESS)) {
120 0 : ADIAG_ERR("get trace struct field failed, object name=%s, struct name=%s.", objName, rb->entry[i].name);
121 0 : return TRACE_FAILURE;
122 : }
123 : }
124 : }
125 21 : return TRACE_SUCCESS;
126 : }
127 :
128 21 : STATIC TraStatus TracerScheduleSaveDataHead(const RbLog *rb, int32_t fd, const char *objName)
129 : {
130 21 : TraceStructDataHead dataHead = { 0 };
131 21 : dataHead.msgSize = rb->head.msgSize;
132 21 : dataHead.msgTxtSize = rb->head.msgTxtSize;
133 21 : dataHead.msgNum = TracerRbLogGetMsgNum(rb);
134 21 : if (TraceRecorderWrite(fd, (char *)&dataHead, (uint32_t)sizeof(TraceStructDataHead)) != TRACE_SUCCESS) {
135 0 : ADIAG_ERR("write data head failed, object name=%s.", objName);
136 0 : return TRACE_FAILURE;
137 : }
138 21 : return TRACE_SUCCESS;
139 : }
140 :
141 21 : STATIC TraStatus TracerScheduleSaveStruct(const struct RbLog *newRb, int32_t fd, const char *objName)
142 : {
143 21 : if (TracerScheduleSaveTraceCtrl(newRb, fd, objName) != TRACE_SUCCESS) {
144 0 : ADIAG_ERR("write log ctrl failed, object name=%s.", objName);
145 0 : return TRACE_FAILURE;
146 : }
147 :
148 21 : if (TracerScheduleSaveStructSegment(newRb, fd, objName) != TRACE_SUCCESS) {
149 0 : ADIAG_ERR("write struct segment failed, object name=%s.", objName);
150 0 : return TRACE_FAILURE;
151 : }
152 :
153 21 : if (TracerScheduleSaveDataHead(newRb, fd, objName) != TRACE_SUCCESS) {
154 0 : ADIAG_ERR("write data head failed, object name=%s.", objName);
155 0 : return TRACE_FAILURE;
156 : }
157 21 : return TRACE_SUCCESS;
158 : }
159 :
160 : /**
161 : * @brief save msg to file with binary file
162 : * @param [in] newRb: ringbuffer
163 : * @param [in] timeStr: time stamp of file name
164 : * @param [in] objName: object name
165 : * @return NA
166 : */
167 41 : void TracerScheduleSaveObjBinData(struct RbLog *newRb, const char *timeStr, const char *eventName, const char *objName)
168 : {
169 41 : TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, objName, TRACE_FILE_BIN_SUFFIX };
170 41 : TraceDirInfo dirInfo = { eventName, TraceGetPid(), timeStr, false };
171 41 : int32_t fd = -1;
172 :
173 41 : char *txt = NULL;
174 41 : uint32_t txtLen = 0;
175 41 : TraStatus ret = TRACE_SUCCESS;
176 : do {
177 62 : ret = TraceRbLogReadOriRbMsg(newRb, &txt, &txtLen);
178 62 : if (ret == TRACE_RING_BUFFER_EMPTY) {
179 41 : break;
180 : }
181 21 : if (ret != TRACE_SUCCESS) {
182 0 : ADIAG_ERR("read log msg failed, ret : %d", ret);
183 0 : break;
184 : }
185 :
186 42 : if ((fd == -1) && ((TraceRecorderGetFd(&dirInfo, &fileInfo, &fd) != TRACE_SUCCESS) ||
187 21 : (TracerScheduleSaveStruct(newRb, fd, objName) != TRACE_SUCCESS))) {
188 0 : ADIAG_ERR("get file fd failed, object name=%s.", objName);
189 0 : break;
190 : }
191 21 : (void)TraceRecorderWrite(fd, txt, txtLen);
192 21 : } while (ret == TRACE_SUCCESS);
193 41 : TraceClose(&fd);
194 41 : return;
195 : }
196 :
197 : /**
198 : * @brief save msg to file with txt file, must be reentrant, cannot print msg
199 : * @param [in] newRb: ringbuffer
200 : * @param [in] timeStr: time stamp of file name
201 : * @param [in] objName: object name
202 : * @return NA
203 : */
204 41 : STATIC void TracerScheduleSaveObjDataSafe(struct RbLog *newRb, const char *timeStr, const char *objName)
205 : {
206 41 : TraceDirInfo dirInfo = { TRACER_STACKCORE_NAME, TraceGetPid(), timeStr, false };
207 41 : TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, objName, TRACE_FILE_TXT_SUFFIX };
208 41 : int32_t fd = -1;
209 41 : char *txt = NULL;
210 41 : char timestamp[TIMESTAMP_MAX_LENGTH] = {0};
211 41 : TraStatus ret = TRACE_SUCCESS;
212 : do {
213 61 : ret = TraceRbLogReadRbMsgSafe(newRb, (char *)×tamp, TIMESTAMP_MAX_LENGTH, &txt);
214 61 : if (ret == TRACE_RING_BUFFER_EMPTY) {
215 41 : break;
216 : }
217 20 : if (ret != TRACE_SUCCESS) {
218 0 : break;
219 : }
220 40 : if ((fd == -1) &&
221 20 : (TraceRecorderSafeGetFd(&dirInfo, &fileInfo, &fd) != TRACE_SUCCESS)) {
222 0 : break;
223 : }
224 20 : uint32_t txtLen = (uint32_t)strlen(txt);
225 20 : (void)TraceRecorderWrite(fd, timestamp, (uint32_t)strlen(timestamp));
226 20 : (void)TraceRecorderWrite(fd, txt, txtLen);
227 20 : if ((txtLen > 0) && (txt[txtLen - 1U] != '\n')) {
228 20 : (void)TraceRecorderWrite(fd, "\n", 1);
229 : }
230 20 : } while (ret == TRACE_SUCCESS);
231 41 : TraceClose(&fd);
232 41 : return;
233 : }
234 :
235 21 : STATIC TraStatus TracerScheduleSaveTraceCtrlSafe(const RbLog *rb, int32_t fd)
236 : {
237 21 : TraceCtrlHead traceCtrl = { 0 };
238 21 : traceCtrl.magic = TRACE_MAGIC;
239 21 : traceCtrl.version = TRACE_VERSION;
240 21 : traceCtrl.dataSize = rb->head.msgSize * TracerRbLogGetMsgNum(rb);
241 21 : traceCtrl.realTime = rb->head.realTime;
242 21 : traceCtrl.minutesWest = rb->head.minutesWest;
243 21 : traceCtrl.cpuFreq = rb->head.cpuFreq;
244 21 : traceCtrl.structSize = (uint32_t)sizeof(TraceStructSegmentHead);
245 231 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
246 210 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList *)rb->entry[i].list)->list))) {
247 189 : continue;
248 : }
249 21 : traceCtrl.structSize += (uint32_t)sizeof(TraceStructHead) +
250 21 : ((struct AdiagList *)rb->entry[i].list)->cnt * (uint32_t)sizeof(TraceStructField);
251 : }
252 :
253 21 : if (TraceRecorderWrite(fd, (char *)&traceCtrl, (uint32_t)sizeof(TraceCtrlHead)) != TRACE_SUCCESS) {
254 0 : return TRACE_FAILURE;
255 : }
256 21 : return TRACE_SUCCESS;
257 : }
258 :
259 21 : STATIC TraStatus TracerScheduleSaveStructSegmentSafe(const RbLog *rb, int32_t fd)
260 : {
261 21 : TraceStructSegmentHead structSegmentHead = { 0 };
262 231 : for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
263 210 : if ((rb->entry[i].list == NULL) || (ListEmpty(&((struct AdiagList *)rb->entry[i].list)->list))) {
264 189 : continue;
265 : }
266 21 : structSegmentHead.structCount++;
267 : }
268 21 : if (TraceRecorderWrite(fd, (char *)&structSegmentHead, (uint32_t)sizeof(TraceStructSegmentHead)) != TRACE_SUCCESS) {
269 0 : return TRACE_FAILURE;
270 : }
271 :
272 231 : for (uint8_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
273 210 : struct AdiagList *traList = (struct AdiagList *)(rb->entry[i].list);
274 210 : if ((traList == NULL) || (ListEmpty(&traList->list))) {
275 189 : continue;
276 : }
277 21 : TraceStructHead structHead = { 0 };
278 21 : structHead.structType = i;
279 21 : structHead.itemNum = ((struct AdiagList *)rb->entry[i].list)->cnt;
280 21 : errno_t err = strcpy_s(structHead.structName, TRACE_NAME_LENGTH, rb->entry[i].name);
281 : if (err != EOK) {
282 : }
283 21 : if (TraceRecorderWrite(fd, (char *)&structHead, (uint32_t)sizeof(TraceStructHead)) != TRACE_SUCCESS) {
284 0 : continue;
285 : }
286 :
287 21 : struct AdiagListNode *node = NULL;
288 21 : struct ListHead *pos = NULL;
289 :
290 231 : LIST_FOR_EACH(pos, &traList->list) {
291 210 : node = LIST_ENTRY(pos, struct AdiagListNode, list);
292 420 : if ((node == NULL) ||
293 210 : (TraceRecorderWrite(fd, node->data, (uint32_t)sizeof(TraceStructField)) != TRACE_SUCCESS)) {
294 0 : return TRACE_FAILURE;
295 : }
296 : }
297 : }
298 21 : return TRACE_SUCCESS;
299 : }
300 :
301 21 : STATIC TraStatus TracerScheduleSaveDataHeadSafe(const RbLog *rb, int32_t fd)
302 : {
303 21 : TraceStructDataHead dataHead = { 0 };
304 21 : dataHead.msgSize = rb->head.msgSize;
305 21 : dataHead.msgTxtSize = rb->head.msgTxtSize;
306 21 : dataHead.msgNum = TracerRbLogGetMsgNum(rb);
307 21 : if (TraceRecorderWrite(fd, (char *)&dataHead, (uint32_t)sizeof(TraceStructDataHead)) != TRACE_SUCCESS) {
308 0 : return TRACE_FAILURE;
309 : }
310 21 : return TRACE_SUCCESS;
311 : }
312 :
313 21 : STATIC TraStatus TracerScheduleSaveStructSafe(const struct RbLog *newRb, int32_t fd)
314 : {
315 21 : if (TracerScheduleSaveTraceCtrlSafe(newRb, fd) != TRACE_SUCCESS) {
316 0 : return TRACE_FAILURE;
317 : }
318 :
319 21 : if (TracerScheduleSaveStructSegmentSafe(newRb, fd) != TRACE_SUCCESS) {
320 0 : return TRACE_FAILURE;
321 : }
322 :
323 21 : if (TracerScheduleSaveDataHeadSafe(newRb, fd) != TRACE_SUCCESS) {
324 0 : return TRACE_FAILURE;
325 : }
326 21 : return TRACE_SUCCESS;
327 : }
328 :
329 : /**
330 : * @brief save msg to file with binary file, must be reentrant, cannot print msg
331 : * @param [in] newRb: ringbuffer
332 : * @param [in] timeStr: time stamp of file name
333 : * @param [in] objName: object name
334 : * @return NA
335 : */
336 21 : STATIC void TracerScheduleSaveObjBinDataSafe(struct RbLog *newRb, const char *timeStr, const char *objName)
337 : {
338 21 : TraceDirInfo dirInfo = { TRACER_STACKCORE_NAME, TraceGetPid(), timeStr, false};
339 21 : TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, objName, TRACE_FILE_BIN_SUFFIX };
340 21 : int32_t fd = -1;
341 21 : char *txt = NULL;
342 21 : uint32_t txtLen = 0;
343 21 : TraStatus ret = TRACE_SUCCESS;
344 21 : uint64_t cycle = 0;
345 : do {
346 42 : ret = TraceRbLogReadOriRbMsgSafe(newRb, &txt, &txtLen, &cycle);
347 42 : if (ret == TRACE_RING_BUFFER_EMPTY) {
348 21 : break;
349 : }
350 21 : if (ret != TRACE_SUCCESS) {
351 0 : break;
352 : }
353 42 : if ((fd == -1) &&
354 42 : ((TraceRecorderSafeGetFd(&dirInfo, &fileInfo, &fd) != TRACE_SUCCESS) ||
355 21 : (TracerScheduleSaveStructSafe(newRb, fd) != TRACE_SUCCESS))) {
356 : break;
357 : }
358 21 : (void)TraceRecorderWrite(fd, txt, txtLen);
359 21 : } while (ret == TRACE_SUCCESS);
360 21 : TraceClose(&fd);
361 21 : return;
362 : }
363 :
364 : /**
365 : * @brief save msg to file with binary file, must be reentrant, cannot print msg
366 : * @param [in] tracer: tracer pointer
367 : * @param [in] timeStamp: timestamp
368 : * @return NA
369 : */
370 119 : TraStatus TracerScheduleSafeSave(Tracer *tracer, uint64_t timeStamp)
371 : {
372 119 : if (tracer->mgr == NULL) {
373 20 : return TRACE_FAILURE;
374 : }
375 99 : char dirTimeStr[TIMESTAMP_MAX_LENGTH] = {0};
376 99 : TraStatus ret = TimestampToFileStr(timeStamp, dirTimeStr, TIMESTAMP_MAX_LENGTH);
377 99 : if (ret != TRACE_SUCCESS) {
378 0 : return TRACE_FAILURE;
379 : }
380 9999 : for (int32_t i = 0; i < MAX_OBJECT_NUM; i++) {
381 9900 : if ((tracer->mgr->obj[i].status != (int32_t)OBJ_STATUS_WORKING) || (tracer->mgr->obj[i].pid != TraceGetPid())) {
382 9838 : continue;
383 : }
384 : // read from ringbuffer, then write to file
385 62 : struct RbLog *rb = (RbLog *)tracer->mgr->obj[i].data;
386 62 : TraceRbLogPrepareForRead(rb);
387 62 : if (TracerScheduleCheckListEmpty(rb)) {
388 41 : TracerScheduleSaveObjDataSafe(rb, dirTimeStr, tracer->mgr->obj[i].name);
389 : } else {
390 21 : TracerScheduleSaveObjBinDataSafe(rb, dirTimeStr, tracer->mgr->obj[i].name);
391 : }
392 : }
393 :
394 99 : return TRACE_SUCCESS;
395 : }
|