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