已合并
fix: prevent atrace dir aging race #2658
GuoWenbo创建于 6月6日
fix: prevent atrace dir aging race #2658
已合并
共 2 个文件变更+344-17
| @@ -288,6 +288,21 @@ STATIC void TraceRecorderListAppend(TraceDirList *dirList, TraceDirNode *newNode | |||
| 288 | (void)AdiagLockRelease(&dirList->lock); | 288 | (void)AdiagLockRelease(&dirList->lock); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | +STATIC TraceDirNode *TraceRecorderListFind(TraceDirList *dirList, const char *dirPath) | ||
| 292 | +{ | ||
| 293 | + (void)AdiagLockGet(&dirList->lock); | ||
| 294 | + TraceDirNode *curNode = dirList->head; | ||
| 295 | + while (curNode != NULL) { | ||
| 296 | + if (strcmp(curNode->dirPath, dirPath) == 0) { | ||
| 297 | + (void)AdiagLockRelease(&dirList->lock); | ||
| 298 | + return curNode; | ||
| 299 | + } | ||
| 300 | + curNode = curNode->next; | ||
| 301 | + } | ||
| 302 | + (void)AdiagLockRelease(&dirList->lock); | ||
| 303 | + return NULL; | ||
| 304 | +} | ||
| 305 | + | ||
| 291 | STATIC void TraceRecorderSaveNode(const TraceDirInfo *dirInfo, TraceDirNode *dirNew) | 306 | STATIC void TraceRecorderSaveNode(const TraceDirInfo *dirInfo, TraceDirNode *dirNew) |
| 292 | { | 307 | { |
| 293 | // if exit_event, no need to aging | 308 | // if exit_event, no need to aging |
| @@ -367,6 +382,15 @@ const TraceDirNode *TraceRecorderGetDirPath(const TraceDirInfo *dirInfo) | |||
| 367 | return NULL; | 382 | return NULL; |
| 368 | } | 383 | } |
| 369 | 384 | ||
| 385 | + if (strncmp(dirInfo->eventName, TRACER_EVENT_EXIT, strlen(TRACER_EVENT_EXIT)) != 0) { | ||
| 386 | + TraceDirList *dirList = (dirInfo->isDevice) ? &g_recorderMgr->deviceDirList : &g_recorderMgr->hostDirList; | ||
| 387 | + TraceDirNode *existNode = TraceRecorderListFind(dirList, dirNew->dirPath); | ||
| 388 | + if (existNode != NULL) { | ||
| 389 | + ADIAG_SAFE_FREE(dirNew); | ||
| 390 | + return existNode; | ||
| 391 | + } | ||
| 392 | + } | ||
| 393 | + | ||
| 370 | TraceRecorderSaveNode(dirInfo, dirNew); | 394 | TraceRecorderSaveNode(dirInfo, dirNew); |
| 371 | return dirNew; | 395 | return dirNew; |
| 372 | } | 396 | } |
| @@ -386,15 +410,18 @@ TraStatus TraceRecorderGetFd(const TraceDirInfo *dirInfo, const TraceFileInfo *f | |||
| 386 | char filePath[MAX_FULLPATH_LEN + 1U] = { 0 }; | 410 | char filePath[MAX_FULLPATH_LEN + 1U] = { 0 }; |
| 387 | int32_t ret = snprintf_s(filePath, MAX_FULLPATH_LEN + 1U, MAX_FULLPATH_LEN, | 411 | int32_t ret = snprintf_s(filePath, MAX_FULLPATH_LEN + 1U, MAX_FULLPATH_LEN, |
| 388 | "%s/%s_tracer_%s%s", dir->dirPath, fileInfo->tracerName, fileInfo->objName, fileInfo->suffix); | 412 | "%s/%s_tracer_%s%s", dir->dirPath, fileInfo->tracerName, fileInfo->objName, fileInfo->suffix); |
| 389 | - (void)AdiagLockRelease(&g_recorderMgr->lock); | ||
| 390 | if (ret == -1) { | 413 | if (ret == -1) { |
| 391 | - ADIAG_ERR("snprintf_s file path failed, ret=%d, strerr=%s.", ret, strerror(AdiagGetErrorCode())); | 414 | + int32_t errCode = AdiagGetErrorCode(); |
| 415 | + (void)AdiagLockRelease(&g_recorderMgr->lock); | ||
| 416 | + ADIAG_ERR("snprintf_s file path failed, ret=%d, strerr=%s.", ret, strerror(errCode)); | ||
| 392 | return TRACE_FAILURE; | 417 | return TRACE_FAILURE; |
| 393 | } | 418 | } |
| 394 | int32_t fileFd = TraceOpen(filePath, (uint32_t)O_CREAT | (uint32_t)O_WRONLY | (uint32_t)O_APPEND, | 419 | int32_t fileFd = TraceOpen(filePath, (uint32_t)O_CREAT | (uint32_t)O_WRONLY | (uint32_t)O_APPEND, |
| 395 | TRACE_FILE_MODE); | 420 | TRACE_FILE_MODE); |
| 421 | + int32_t errCode = (fileFd < 0) ? AdiagGetErrorCode() : 0; | ||
| 422 | + (void)AdiagLockRelease(&g_recorderMgr->lock); | ||
| 396 | ADIAG_CHK_EXPR_ACTION(fileFd < 0, return TRACE_FAILURE, | 423 | ADIAG_CHK_EXPR_ACTION(fileFd < 0, return TRACE_FAILURE, |
| 397 | - "open file failed, file=%s, strerr=%s.", filePath, strerror(AdiagGetErrorCode())); | 424 | + "open file failed, file=%s, strerr=%s.", filePath, strerror(errCode)); |
| 398 | 425 | ||
| 399 | *fd = fileFd; | 426 | *fd = fileFd; |
| 400 | return TRACE_SUCCESS; | 427 | return TRACE_SUCCESS; |
| @@ -14,11 +14,105 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | -#include "mmpa_api.h" | 17 | +#include "mmpa_api.h" |
| 18 | -#include "trace_types.h" | 18 | +#include "trace_types.h" |
| 19 | -#include "trace_system_api.h" | 19 | +#include "trace_system_api.h" |
| 20 | - | 20 | +#include <atomic> |
| 21 | -#define TIMESTAMP_MAX_LENGTH 29U | 21 | +#include <cerrno> |
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +static std::atomic<uint32_t> g_traceOpenCallIndex(0); | ||
| 28 | +static std::atomic<bool> g_firstTraceOpenEntered(false); | ||
| 29 | +static std::atomic<bool> g_allowFirstTraceOpen(false); | ||
| 30 | +static std::atomic<bool> g_agingThreadDone(false); | ||
| 31 | + | ||
| 32 | +typedef struct { | ||
| 33 | + TraceDirInfo dirInfo; | ||
| 34 | + TraceFileInfo fileInfo; | ||
| 35 | + char dirTime[TIMESTAMP_MAX_LENGTH]; | ||
| 36 | + TraStatus ret; | ||
| 37 | + int32_t fd; | ||
| 38 | + int32_t err; | ||
| 39 | +} TraceGetFdThreadArg; | ||
| 40 | + | ||
| 41 | +typedef struct { | ||
| 42 | + bool success; | ||
| 43 | +} TraceAgingThreadArg; | ||
| 44 | + | ||
| 45 | +int32_t TraceOpenBlockFirstThenOpen(const char *filePath, int32_t flag, uint32_t mode) | ||
| 46 | +{ | ||
| 47 | + uint32_t callIndex = g_traceOpenCallIndex.fetch_add(1); | ||
| 48 | + if (callIndex == 0U) { | ||
| 49 | + g_firstTraceOpenEntered.store(true); | ||
| 50 | + while (!g_allowFirstTraceOpen.load()) { | ||
| 51 | + usleep(1000); | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + int32_t fd = open(filePath, flag, mode); | ||
| 56 | + if (fd >= 0) { | ||
| 57 | + (void)fchmod(fd, mode); | ||
| 58 | + } | ||
| 59 | + return fd; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +void *TraceRecorderGetFdThread(void *arg) | ||
| 63 | +{ | ||
| 64 | + TraceGetFdThreadArg *threadArg = static_cast<TraceGetFdThreadArg *>(arg); | ||
| 65 | + errno = 0; | ||
| 66 | + threadArg->ret = TraceRecorderGetFd(&threadArg->dirInfo, &threadArg->fileInfo, &threadArg->fd); | ||
| 67 | + threadArg->err = errno; | ||
| 68 | + if (threadArg->fd >= 0) { | ||
| 69 | + close(threadArg->fd); | ||
| 70 | + } | ||
| 71 | + return NULL; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +void *TraceRecorderCreateAgingDirsThread(void *arg) | ||
| 75 | +{ | ||
| 76 | + TraceAgingThreadArg *threadArg = static_cast<TraceAgingThreadArg *>(arg); | ||
| 77 | + threadArg->success = true; | ||
| 78 | + for (uint32_t i = 0; i < 10U; i++) { | ||
| 79 | + char timeStr[TIMESTAMP_MAX_LENGTH] = {0}; | ||
| 80 | + int32_t ret = snprintf_s(timeStr, TIMESTAMP_MAX_LENGTH, TIMESTAMP_MAX_LENGTH - 1U, | ||
| 81 | + "1970010108000001%04u", i); | ||
| 82 | + if (ret == -1) { | ||
| 83 | + threadArg->success = false; | ||
| 84 | + break; | ||
| 85 | + } | ||
| 86 | + TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), timeStr, true }; | ||
| 87 | + TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "other", TRACE_FILE_TXT_SUFFIX }; | ||
| 88 | + int32_t fd = -1; | ||
| 89 | + if (TraceRecorderGetFd(&dirInfo, &fileInfo, &fd) != TRACE_SUCCESS) { | ||
| 90 | + threadArg->success = false; | ||
| 91 | + break; | ||
| 92 | + } | ||
| 93 | + close(fd); | ||
| 94 | + } | ||
| 95 | + g_agingThreadDone.store(true); | ||
| 96 | + return NULL; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +bool BuildRecorderDirPath(char *path, size_t len, const char *eventName, const char *dirTime) | ||
| 100 | +{ | ||
| 101 | + int32_t ret = snprintf_s(path, len, len - 1U, "%s/atrace/trace_%d_%d_%s/%s_event_%d_%s", | ||
| 102 | + LLT_TEST_DIR, TraceAttrGetPgid(), TraceAttrGetPid(), TraceAttrGetTime(), eventName, getpid(), dirTime); | ||
| 103 | + return ret != -1; | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +bool BuildRecorderFilePath(char *path, size_t len, const char *eventName, const char *dirTime, | ||
| 107 | + const char *tracerName, const char *objName, const char *suffix) | ||
| 108 | +{ | ||
| 109 | + char dirPath[MAX_FULLPATH_LEN + 1U] = {0}; | ||
| 110 | + if (!BuildRecorderDirPath(dirPath, MAX_FULLPATH_LEN + 1U, eventName, dirTime)) { | ||
| 111 | + return false; | ||
| 112 | + } | ||
| 113 | + int32_t ret = snprintf_s(path, len, len - 1U, "%s/%s_tracer_%s%s", dirPath, tracerName, objName, suffix); | ||
| 114 | + return ret != -1; | ||
| 115 | +} | ||
| 22 | 116 | ||
| 23 | class TraceRecorderUtest: public testing::Test { | 117 | class TraceRecorderUtest: public testing::Test { |
| 24 | protected: | 118 | protected: |
| @@ -247,8 +341,8 @@ TEST_F(TraceRecorderUtest, TestSafeGetBinFd) | |||
| 247 | EXPECT_EQ(TRACE_SUCCESS, ret); | 341 | EXPECT_EQ(TRACE_SUCCESS, ret); |
| 248 | } | 342 | } |
| 249 | 343 | ||
| 250 | -TEST_F(TraceRecorderUtest, TraceRecorderGetFd_Failed) | 344 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_Failed) |
| 251 | -{ | 345 | +{ |
| 252 | char timeStr[TIMESTAMP_MAX_LENGTH] = {0}; | 346 | char timeStr[TIMESTAMP_MAX_LENGTH] = {0}; |
| 253 | auto ret = TimestampToFileStr(std::time(0), timeStr, TIMESTAMP_MAX_LENGTH); | 347 | auto ret = TimestampToFileStr(std::time(0), timeStr, TIMESTAMP_MAX_LENGTH); |
| 254 | EXPECT_EQ(TRACE_SUCCESS, ret); | 348 | EXPECT_EQ(TRACE_SUCCESS, ret); |
| @@ -258,12 +352,218 @@ TEST_F(TraceRecorderUtest, TraceRecorderGetFd_Failed) | |||
| 258 | int32_t fd = -1; | 352 | int32_t fd = -1; |
| 259 | MOCKER(TraceRecorderGetDirPath).stubs().will(returnValue((const TraceDirNode *)0)); | 353 | MOCKER(TraceRecorderGetDirPath).stubs().will(returnValue((const TraceDirNode *)0)); |
| 260 | ret = TraceRecorderGetFd(&dirInfo, &info, &fd); | 354 | ret = TraceRecorderGetFd(&dirInfo, &info, &fd); |
| 261 | - EXPECT_EQ(TRACE_FAILURE, ret); | 355 | + EXPECT_EQ(TRACE_FAILURE, ret); |
| 262 | -} | 356 | +} |
| 263 | - | 357 | + |
| 264 | -TEST_F(TraceRecorderUtest, TestTraceRecorderSafeGetFd_Failed) | 358 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_SameDirAgingKeepsWritable) |
| 265 | -{ | 359 | +{ |
| 266 | - auto ret = TraceRecorderSafeGetFd(NULL, NULL, NULL); | 360 | + TraceRecorderExit(); |
| 361 | + setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1); | ||
| 362 | + setenv("ASCEND_TRACE_RECORD_NUM", "10", 1); | ||
| 363 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit()); | ||
| 364 | + | ||
| 365 | + char timeStr[TIMESTAMP_MAX_LENGTH] = {0}; | ||
| 366 | + auto ret = TimestampToFileStr(std::time(0), timeStr, TIMESTAMP_MAX_LENGTH); | ||
| 367 | + EXPECT_EQ(TRACE_SUCCESS, ret); | ||
| 368 | + | ||
| 369 | + TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), timeStr, true }; | ||
| 370 | + TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "ts_0", TRACE_FILE_TXT_SUFFIX }; | ||
| 371 | + for (uint32_t i = 0; i < 11U; i++) { | ||
| 372 | + int32_t fd = -1; | ||
| 373 | + ret = TraceRecorderGetFd(&dirInfo, &fileInfo, &fd); | ||
| 374 | + EXPECT_EQ(TRACE_SUCCESS, ret); | ||
| 375 | + close(fd); | ||
| 376 | + } | ||
| 377 | + | ||
| 378 | + char filePath[MAX_FULLPATH_LEN + 1U] = {0}; | ||
| 379 | + ASSERT_TRUE(BuildRecorderFilePath(filePath, MAX_FULLPATH_LEN + 1U, TRACER_SCHEDULE_NAME, timeStr, | ||
| 380 | + TRACER_SCHEDULE_NAME, "ts_0", TRACE_FILE_TXT_SUFFIX)); | ||
| 381 | + EXPECT_EQ(0, access(filePath, F_OK)); | ||
| 382 | + | ||
| 383 | + unsetenv("ASCEND_TRACE_RECORD_NUM"); | ||
| 384 | + unsetenv("ASCEND_WORK_PATH"); | ||
| 385 | +} | ||
| 386 | + | ||
| 387 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_ConcurrentDirAgingKeepsFirstOpen) | ||
| 388 | +{ | ||
| 389 | + TraceRecorderExit(); | ||
| 390 | + setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1); | ||
| 391 | + setenv("ASCEND_TRACE_RECORD_NUM", "10", 1); | ||
| 392 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit()); | ||
| 393 | + | ||
| 394 | + g_traceOpenCallIndex.store(0); | ||
| 395 | + g_firstTraceOpenEntered.store(false); | ||
| 396 | + g_allowFirstTraceOpen.store(false); | ||
| 397 | + g_agingThreadDone.store(false); | ||
| 398 | + MOCKER(TraceOpen).stubs().will(invoke(TraceOpenBlockFirstThenOpen)); | ||
| 399 | + | ||
| 400 | + TraceGetFdThreadArg firstArg = {}; | ||
| 401 | + int32_t ret = snprintf_s(firstArg.dirTime, TIMESTAMP_MAX_LENGTH, TIMESTAMP_MAX_LENGTH - 1U, | ||
| 402 | + "19700101080000000001"); | ||
| 403 | + EXPECT_NE(-1, ret); | ||
| 404 | + firstArg.dirInfo = { TRACER_SCHEDULE_NAME, getpid(), firstArg.dirTime, true }; | ||
| 405 | + firstArg.fileInfo = { TRACER_SCHEDULE_NAME, "first", TRACE_FILE_TXT_SUFFIX }; | ||
| 406 | + firstArg.fd = -1; | ||
| 407 | + firstArg.ret = TRACE_SUCCESS; | ||
| 408 | + firstArg.err = 0; | ||
| 409 | + | ||
| 410 | + pthread_t threadId = 0; | ||
| 411 | + EXPECT_EQ(0, pthread_create(&threadId, NULL, TraceRecorderGetFdThread, &firstArg)); | ||
| 412 | + for (uint32_t i = 0; i < 5000U && !g_firstTraceOpenEntered.load(); i++) { | ||
| 413 | + usleep(1000); | ||
| 414 | + } | ||
| 415 | + ASSERT_TRUE(g_firstTraceOpenEntered.load()); | ||
| 416 | + | ||
| 417 | + TraceAgingThreadArg agingArg = { true }; | ||
| 418 | + pthread_t agingThreadId = 0; | ||
| 419 | + EXPECT_EQ(0, pthread_create(&agingThreadId, NULL, TraceRecorderCreateAgingDirsThread, &agingArg)); | ||
| 420 | + usleep(100000); | ||
| 421 | + EXPECT_FALSE(g_agingThreadDone.load()); | ||
| 422 | + | ||
| 423 | + g_allowFirstTraceOpen.store(true); | ||
| 424 | + EXPECT_EQ(0, pthread_join(threadId, NULL)); | ||
| 425 | + EXPECT_EQ(0, pthread_join(agingThreadId, NULL)); | ||
| 426 | + EXPECT_EQ(TRACE_SUCCESS, firstArg.ret); | ||
| 427 | + EXPECT_GE(firstArg.fd, 0); | ||
| 428 | + EXPECT_TRUE(agingArg.success); | ||
| 429 | + | ||
| 430 | + GlobalMockObject::verify(); | ||
| 431 | + unsetenv("ASCEND_TRACE_RECORD_NUM"); | ||
| 432 | + unsetenv("ASCEND_WORK_PATH"); | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_WriteCreatesExpectedFile) | ||
| 436 | +{ | ||
| 437 | + TraceRecorderExit(); | ||
| 438 | + setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1); | ||
| 439 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit()); | ||
| 440 | + | ||
| 441 | + const char *dirTime = "19700101080002000001"; | ||
| 442 | + TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTime, true }; | ||
| 443 | + TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "normal", TRACE_FILE_TXT_SUFFIX }; | ||
| 444 | + int32_t fd = -1; | ||
| 445 | + auto ret = TraceRecorderGetFd(&dirInfo, &fileInfo, &fd); | ||
| 446 | + EXPECT_EQ(TRACE_SUCCESS, ret); | ||
| 447 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderWrite(fd, "abc", 3U)); | ||
| 448 | + close(fd); | ||
| 449 | + | ||
| 450 | + char filePath[MAX_FULLPATH_LEN + 1U] = {0}; | ||
| 451 | + ASSERT_TRUE(BuildRecorderFilePath(filePath, MAX_FULLPATH_LEN + 1U, TRACER_SCHEDULE_NAME, dirTime, | ||
| 452 | + TRACER_SCHEDULE_NAME, "normal", TRACE_FILE_TXT_SUFFIX)); | ||
| 453 | + EXPECT_EQ(0, access(filePath, F_OK)); | ||
| 454 | + | ||
| 455 | + unsetenv("ASCEND_WORK_PATH"); | ||
| 456 | +} | ||
| 457 | + | ||
| 458 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_SameDirWithinLimitKeepsWritable) | ||
| 459 | +{ | ||
| 460 | + TraceRecorderExit(); | ||
| 461 | + setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1); | ||
| 462 | + setenv("ASCEND_TRACE_RECORD_NUM", "10", 1); | ||
| 463 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit()); | ||
| 464 | + | ||
| 465 | + const char *dirTime = "19700101080002000002"; | ||
| 466 | + TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTime, true }; | ||
| 467 | + TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "repeat", TRACE_FILE_TXT_SUFFIX }; | ||
| 468 | + for (uint32_t i = 0; i < 2U; i++) { | ||
| 469 | + int32_t fd = -1; | ||
| 470 | + auto ret = TraceRecorderGetFd(&dirInfo, &fileInfo, &fd); | ||
| 471 | + EXPECT_EQ(TRACE_SUCCESS, ret); | ||
| 472 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderWrite(fd, "x", 1U)); | ||
| 473 | + close(fd); | ||
| 474 | + } | ||
| 475 | + | ||
| 476 | + char filePath[MAX_FULLPATH_LEN + 1U] = {0}; | ||
| 477 | + ASSERT_TRUE(BuildRecorderFilePath(filePath, MAX_FULLPATH_LEN + 1U, TRACER_SCHEDULE_NAME, dirTime, | ||
| 478 | + TRACER_SCHEDULE_NAME, "repeat", TRACE_FILE_TXT_SUFFIX)); | ||
| 479 | + EXPECT_EQ(0, access(filePath, F_OK)); | ||
| 480 | + | ||
| 481 | + unsetenv("ASCEND_TRACE_RECORD_NUM"); | ||
| 482 | + unsetenv("ASCEND_WORK_PATH"); | ||
| 483 | +} | ||
| 484 | + | ||
| 485 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_UniqueDirAgingRemovesOldestOnly) | ||
| 486 | +{ | ||
| 487 | + TraceRecorderExit(); | ||
| 488 | + setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1); | ||
| 489 | + setenv("ASCEND_TRACE_RECORD_NUM", "10", 1); | ||
| 490 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit()); | ||
| 491 | + | ||
| 492 | + char dirPaths[11][MAX_FULLPATH_LEN + 1U] = {}; | ||
| 493 | + for (uint32_t i = 0; i < 11U; i++) { | ||
| 494 | + char dirTime[TIMESTAMP_MAX_LENGTH] = {0}; | ||
| 495 | + int32_t ret = snprintf_s(dirTime, TIMESTAMP_MAX_LENGTH, TIMESTAMP_MAX_LENGTH - 1U, | ||
| 496 | + "1970010108000201%04u", i); | ||
| 497 | + EXPECT_NE(-1, ret); | ||
| 498 | + ASSERT_TRUE(BuildRecorderDirPath(dirPaths[i], MAX_FULLPATH_LEN + 1U, TRACER_SCHEDULE_NAME, dirTime)); | ||
| 499 | + | ||
| 500 | + TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTime, true }; | ||
| 501 | + TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "unique", TRACE_FILE_TXT_SUFFIX }; | ||
| 502 | + int32_t fd = -1; | ||
| 503 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderGetFd(&dirInfo, &fileInfo, &fd)); | ||
| 504 | + close(fd); | ||
| 505 | + } | ||
| 506 | + | ||
| 507 | + EXPECT_NE(0, access(dirPaths[0], F_OK)); | ||
| 508 | + for (uint32_t i = 1; i < 11U; i++) { | ||
| 509 | + EXPECT_EQ(0, access(dirPaths[i], F_OK)); | ||
| 510 | + } | ||
| 511 | + | ||
| 512 | + unsetenv("ASCEND_TRACE_RECORD_NUM"); | ||
| 513 | + unsetenv("ASCEND_WORK_PATH"); | ||
| 514 | +} | ||
| 515 | + | ||
| 516 | +TEST_F(TraceRecorderUtest, TraceRecorderGetFd_ReusedOldDirDoesNotRefreshAgingOrder) | ||
| 517 | +{ | ||
| 518 | + TraceRecorderExit(); | ||
| 519 | + setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1); | ||
| 520 | + setenv("ASCEND_TRACE_RECORD_NUM", "10", 1); | ||
| 521 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit()); | ||
| 522 | + | ||
| 523 | + char dirPaths[11][MAX_FULLPATH_LEN + 1U] = {}; | ||
| 524 | + char dirTimes[11][TIMESTAMP_MAX_LENGTH] = {}; | ||
| 525 | + for (uint32_t i = 0; i < 10U; i++) { | ||
| 526 | + int32_t ret = snprintf_s(dirTimes[i], TIMESTAMP_MAX_LENGTH, TIMESTAMP_MAX_LENGTH - 1U, | ||
| 527 | + "1970010108000301%04u", i); | ||
| 528 | + EXPECT_NE(-1, ret); | ||
| 529 | + ASSERT_TRUE(BuildRecorderDirPath(dirPaths[i], MAX_FULLPATH_LEN + 1U, TRACER_SCHEDULE_NAME, dirTimes[i])); | ||
| 530 | + | ||
| 531 | + TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTimes[i], true }; | ||
| 532 | + TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "timestamp", TRACE_FILE_TXT_SUFFIX }; | ||
| 533 | + int32_t fd = -1; | ||
| 534 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderGetFd(&dirInfo, &fileInfo, &fd)); | ||
| 535 | + close(fd); | ||
| 536 | + } | ||
| 537 | + | ||
| 538 | + TraceDirInfo reusedDirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTimes[0], true }; | ||
| 539 | + TraceFileInfo reusedFileInfo = { TRACER_SCHEDULE_NAME, "reuse", TRACE_FILE_TXT_SUFFIX }; | ||
| 540 | + int32_t reusedFd = -1; | ||
| 541 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderGetFd(&reusedDirInfo, &reusedFileInfo, &reusedFd)); | ||
| 542 | + close(reusedFd); | ||
| 543 | + | ||
| 544 | + int32_t ret = snprintf_s(dirTimes[10], TIMESTAMP_MAX_LENGTH, TIMESTAMP_MAX_LENGTH - 1U, | ||
| 545 | + "1970010108000301%04u", 10U); | ||
| 546 | + EXPECT_NE(-1, ret); | ||
| 547 | + ASSERT_TRUE(BuildRecorderDirPath(dirPaths[10], MAX_FULLPATH_LEN + 1U, TRACER_SCHEDULE_NAME, dirTimes[10])); | ||
| 548 | + | ||
| 549 | + TraceDirInfo newDirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTimes[10], true }; | ||
| 550 | + TraceFileInfo newFileInfo = { TRACER_SCHEDULE_NAME, "timestamp", TRACE_FILE_TXT_SUFFIX }; | ||
| 551 | + int32_t newFd = -1; | ||
| 552 | + EXPECT_EQ(TRACE_SUCCESS, TraceRecorderGetFd(&newDirInfo, &newFileInfo, &newFd)); | ||
| 553 | + close(newFd); | ||
| 554 | + | ||
| 555 | + EXPECT_NE(0, access(dirPaths[0], F_OK)); | ||
| 556 | + for (uint32_t i = 1; i < 11U; i++) { | ||
| 557 | + EXPECT_EQ(0, access(dirPaths[i], F_OK)); | ||
| 558 | + } | ||
| 559 | + | ||
| 560 | + unsetenv("ASCEND_TRACE_RECORD_NUM"); | ||
| 561 | + unsetenv("ASCEND_WORK_PATH"); | ||
| 562 | +} | ||
| 563 | + | ||
| 564 | +TEST_F(TraceRecorderUtest, TestTraceRecorderSafeGetFd_Failed) | ||
| 565 | +{ | ||
| 566 | + auto ret = TraceRecorderSafeGetFd(NULL, NULL, NULL); | ||
| 267 | EXPECT_EQ(TRACE_INVALID_PARAM, ret); | 567 | EXPECT_EQ(TRACE_INVALID_PARAM, ret); |
| 268 | 568 | ||
| 269 | char timeStr[TIMESTAMP_MAX_LENGTH] = {0}; | 569 | char timeStr[TIMESTAMP_MAX_LENGTH] = {0}; |
| @@ -363,4 +663,4 @@ TEST_F(TraceRecorderUtest, TestTraceRecorderSafeGetDirPath_Failed) | |||
| 363 | 663 | ||
| 364 | MOCKER(vsnprintf_s).stubs().will(returnValue(-1)); | 664 | MOCKER(vsnprintf_s).stubs().will(returnValue(-1)); |
| 365 | EXPECT_EQ(TRACE_FAILURE, TraceRecorderSafeGetDirPath(&dirInfo, path, 1024)); | 665 | EXPECT_EQ(TRACE_FAILURE, TraceRecorderSafeGetDirPath(&dirInfo, path, 1024)); |
| 366 | -} | 666 | +} |