- Timestamp:
- May 1, 2019 4:12:47 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/fs/FsPerf.cpp
r78360 r78361 93 93 * It greatly exceeds the RTPATH_MAX so we can push the limits on windows. */ 94 94 #define FSPERF_MAX_PATH (_32K) 95 96 /** EOF marker character used by the master/slave comms. */ 97 #define FSPERF_EOF 0x1a 98 /** EOF marker character used by the master/slave comms, string version. */ 99 #define FSPERF_EOF_STR "\x1a" 95 100 96 101 /** @def FSPERF_TEST_SENDFILE … … 321 326 kCmdOpt_Copy, 322 327 kCmdOpt_NoCopy, 328 kCmdOpt_Remote, 329 kCmdOpt_NoRemote, 323 330 324 331 kCmdOpt_ShowDuration, … … 414 421 { "--copy", kCmdOpt_Copy, RTGETOPT_REQ_NOTHING }, 415 422 { "--no-copy", kCmdOpt_NoCopy, RTGETOPT_REQ_NOTHING }, 423 { "--remote", kCmdOpt_Remote, RTGETOPT_REQ_NOTHING }, 424 { "--no-remote", kCmdOpt_NoRemote, RTGETOPT_REQ_NOTHING }, 416 425 417 426 { "--show-duration", kCmdOpt_ShowDuration, RTGETOPT_REQ_NOTHING }, … … 471 480 static bool g_fMMap = true; 472 481 static bool g_fCopy = true; 482 static bool g_fRemote = true; 473 483 /** @} */ 474 484 … … 652 662 653 663 654 #if 0 // currently unused655 664 /** 656 665 * Construct a path relative to the comms sub-directory. … … 667 676 return &g_szCommsSubDir[0]; 668 677 } 669 #endif670 678 671 679 … … 707 715 708 716 709 #if 0 // currently unused710 717 /** 711 718 * Creates a file under g_szCommsDir with the given content, then renames it … … 735 742 return rc; 736 743 } 737 #endif738 744 739 745 … … 813 819 if ( RT_SUCCESS(rc) 814 820 && ( cbUsed == 0 815 || pszBuf[cbUsed - 1] != 0x1a))821 || pszBuf[cbUsed - 1] != FSPERF_EOF)) 816 822 rc = VERR_TRY_AGAIN; 817 823 … … 853 859 } 854 860 861 862 /** The comms master sequence number. */ 863 static uint32_t g_iSeqNoMaster = 0; 864 865 866 /** 867 * Sends a script to the remote comms slave. 868 * 869 * @returns IPRT status code giving the scripts execution status. 870 * @param pszScript The script. 871 */ 872 static int FsPerfCommsSend(const char *pszScript) 873 { 874 /* 875 * Make sure the script is correctly terminated with an EOF control character. 876 */ 877 size_t const cchScript = strlen(pszScript); 878 AssertReturn(cchScript > 0 && pszScript[cchScript - 1] == FSPERF_EOF, VERR_INVALID_PARAMETER); 879 880 /* 881 * Make sure the comms slave is running. 882 */ 883 if (!RTFileExists(InCommsDir(RT_STR_TUPLE("slave.pid")))) 884 return VERR_PIPE_NOT_CONNECTED; 885 886 /* 887 * Format all the names we might want to check for. 888 */ 889 char szSendNm[32]; 890 size_t const cchSendNm = RTStrPrintf(szSendNm, sizeof(szSendNm), "%u-order.send", g_iSeqNoMaster); 891 892 char szAckNm[64]; 893 size_t const cchAckNm = RTStrPrintf(szAckNm, sizeof(szAckNm), "%u-order.ack", g_iSeqNoMaster); 894 895 /* 896 * Produce the script file and submit it. 897 */ 898 int rc = FsPerfCommsWriteFileAndRename(szSendNm, cchSendNm, pszScript, cchScript); 899 if (RT_SUCCESS(rc)) 900 { 901 g_iSeqNoMaster++; 902 903 /* 904 * Wait for the result. 905 */ 906 uint64_t const msTimeout = RT_MS_1MIN / 2; 907 uint64_t msStart = RTTimeMilliTS(); 908 uint32_t msSleepX4 = 4; 909 for (;;) 910 { 911 /* Try read the result file: */ 912 char *pszContent = NULL; 913 rc = FsPerfCommsReadFile(g_iSeqNoMaster - 1, "-order.done", &pszContent); 914 if (RT_SUCCESS(rc)) 915 { 916 /* Split the result content into status code and error text: */ 917 char *pszErrorText = strchr(pszContent, '\n'); 918 if (pszErrorText) 919 { 920 *pszErrorText = '\0'; 921 pszErrorText++; 922 } 923 else 924 { 925 char *pszEnd = strchr(pszContent, '\0'); 926 Assert(pszEnd[-1] == FSPERF_EOF); 927 pszEnd[-1] = '\0'; 928 } 929 930 /* Parse the status code: */ 931 int32_t rcRemote = VERR_GENERAL_FAILURE; 932 rc = RTStrToInt32Full(pszContent, 0, &rcRemote); 933 if (rc != VINF_SUCCESS) 934 { 935 RTTestIFailed("FsPerfCommsSend: Failed to convert status code '%s'", pszContent); 936 rcRemote = VERR_GENERAL_FAILURE; 937 } 938 939 /* Display or return the text? */ 940 941 RTMemFree(pszContent); 942 return rcRemote; 943 944 } 945 946 if (rc == VERR_TRY_AGAIN) 947 msSleepX4 = 4; 948 949 /* Check for timeout. */ 950 if (RTTimeMilliTS() - msStart > msTimeout) 951 { 952 rc = RTFileDelete(InCommsSubDir(szSendNm, cchSendNm)); 953 if (RT_SUCCESS(rc)) 954 { 955 g_iSeqNoMaster--; 956 rc = VERR_TIMEOUT; 957 } 958 else if (RTFileExists(InCommsDir(szAckNm, cchAckNm))) 959 rc = VERR_PIPE_BUSY; 960 else 961 rc = VERR_PIPE_IO_ERROR; 962 break; 963 } 964 965 /* Sleep a little while. */ 966 msSleepX4++; 967 RTThreadSleep(msSleepX4 / 4); 968 } 969 } 970 return rc; 971 } 972 973 974 /** 975 * Shuts down the comms slave if it exists. 976 */ 977 static void FsPerfCommsShutdownSlave(void) 978 { 979 static bool s_fAlreadyShutdown = false; 980 if (g_szCommsDir[0] != '\0' && !s_fAlreadyShutdown) 981 { 982 s_fAlreadyShutdown = true; 983 FsPerfCommsSend("exit" FSPERF_EOF_STR); 984 985 g_szCommsDir[g_cchCommsDir] = '\0'; 986 int rc = RTDirRemoveRecursive(g_szCommsDir, RTDIRRMREC_F_CONTENT_AND_DIR | (g_fRelativeDir ? RTDIRRMREC_F_NO_ABS_PATH : 0)); 987 if (RT_FAILURE(rc)) 988 RTTestFailed(g_hTest, "RTDirRemoveRecursive(%s,) -> %Rrc\n", g_szCommsDir, rc); 989 } 990 } 991 992 993 994 /********************************************************************************************************************************* 995 * Comms Slave * 996 *********************************************************************************************************************************/ 855 997 856 998 typedef struct FSPERFCOMMSSLAVESTATE … … 1212 1354 1213 1355 offFile += cbThisWrite; 1214 cbToWrite += cbThisWrite;1356 cbToWrite -= cbThisWrite; 1215 1357 } 1216 1358 … … 1477 1619 */ 1478 1620 pState->iLineNo = 0; 1479 while (*pszContent != 0x1a&& *pszContent != '\0')1621 while (*pszContent != FSPERF_EOF && *pszContent != '\0') 1480 1622 { 1481 1623 pState->iLineNo++; … … 1488 1630 else 1489 1631 { 1490 pszEol = strchr(pszLine, 0x1a);1632 pszEol = strchr(pszLine, FSPERF_EOF); 1491 1633 AssertStmt(pszEol, pszEol = strchr(pszLine, '\0')); 1492 1634 pszContent = pszEol; … … 1532 1674 */ 1533 1675 char szTmp[_4K]; 1534 rc = FsPerfCommsWriteFile(RT_STR_TUPLE("slave.pid"), szTmp, RTStrPrintf(szTmp, sizeof(szTmp), "%u\x1a", RTProcSelf())); 1676 rc = FsPerfCommsWriteFile(RT_STR_TUPLE("slave.pid"), szTmp, RTStrPrintf(szTmp, sizeof(szTmp), 1677 "%u" FSPERF_EOF_STR, RTProcSelf())); 1535 1678 if (RT_FAILURE(rc)) 1536 1679 return RTEXITCODE_FAILURE; … … 1562 1705 char szResult[64]; 1563 1706 size_t cchResult = RTStrPrintf(szResult, sizeof(szResult), "%u-order.done", State.iSeqNo); 1564 size_t cchTmp = RTStrPrintf(szTmp, sizeof(szTmp), "%d\n%s \x1a",1707 size_t cchTmp = RTStrPrintf(szTmp, sizeof(szTmp), "%d\n%s" FSPERF_EOF_STR, 1565 1708 rc, RTErrInfoIsSet(&State.ErrInfo.Core) ? State.ErrInfo.Core.pszMsg : ""); 1566 FsPerfCommsWriteFile (szResult, cchResult, szTmp, cchTmp);1709 FsPerfCommsWriteFileAndRename(szResult, cchResult, szTmp, cchTmp); 1567 1710 State.iSeqNo++; 1568 1711 … … 5319 5462 5320 5463 5464 static void fsPerfRemote(void) 5465 { 5466 RTTestISub("remote"); 5467 uint8_t abBuf[16384]; 5468 5469 5470 /* 5471 * Create a file on the remote end and check that we can immediately see it. 5472 */ 5473 RTTESTI_CHECK_RC_RETV(FsPerfCommsSend("reset\n" 5474 "open 0 'file30' 'w' 'ca'\n" 5475 "writepattern 0 0 0 4096\n" FSPERF_EOF_STR), VINF_SUCCESS); 5476 5477 RTFILEACTION enmActuallyTaken = RTFILEACTION_END; 5478 RTFILE hFile0 = NIL_RTFILE; 5479 RTTESTI_CHECK_RC(RTFileOpenEx(InDir(RT_STR_TUPLE("file30")), RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, 5480 &hFile0, &enmActuallyTaken), VINF_SUCCESS); 5481 RTTESTI_CHECK(enmActuallyTaken == RTFILEACTION_OPENED); 5482 RTTESTI_CHECK_RC(RTFileRead(hFile0, abBuf, 4096, NULL), VINF_SUCCESS); 5483 AssertCompile(RT_ELEMENTS(g_abPattern0) == 1); 5484 RTTESTI_CHECK(ASMMemIsAllU8(abBuf, 4096, g_abPattern0[0])); 5485 5486 RTTESTI_CHECK_RC(RTFileClose(hFile0), VINF_SUCCESS); 5487 5488 } 5489 5490 5491 5321 5492 /** 5322 5493 * Display the usage to @a pStrm. … … 5501 5672 g_fMMap = true; 5502 5673 g_fCopy = true; 5674 g_fRemote = true; 5503 5675 break; 5504 5676 … … 5533 5705 g_fMMap = false; 5534 5706 g_fCopy = false; 5707 g_fRemote = false; 5535 5708 break; 5536 5709 … … 5567 5740 CASE_OPT(IgnoreNoCache); 5568 5741 CASE_OPT(Copy); 5742 CASE_OPT(Remote); 5569 5743 5570 5744 CASE_OPT(ShowDuration); … … 5754 5928 if (g_fCopy) 5755 5929 fsPerfCopy(); 5930 if (g_fRemote && g_szCommsDir[0] != '\0') 5931 fsPerfRemote(); 5756 5932 } 5757 5933 5758 /* Cleanup: */ 5934 /* 5935 * Cleanup: 5936 */ 5937 FsPerfCommsShutdownSlave(); 5938 5759 5939 g_szDir[g_cchDir] = '\0'; 5760 5940 rc = RTDirRemoveRecursive(g_szDir, RTDIRRMREC_F_CONTENT_AND_DIR | (g_fRelativeDir ? RTDIRRMREC_F_NO_ABS_PATH : 0)); … … 5768 5948 RTTestFailed(g_hTest, "Test directory already exists: %s\n", g_szDir); 5769 5949 5950 FsPerfCommsShutdownSlave(); 5951 5770 5952 return RTTestSummaryAndDestroy(g_hTest); 5771 5953 }
Note:
See TracChangeset
for help on using the changeset viewer.