VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTFileAio.cpp@ 91886

Last change on this file since 91886 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: tstRTFileAio.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * IPRT Testcase - File Async I/O.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/file.h>
32
33#include <iprt/err.h>
34#include <iprt/mem.h>
35#include <iprt/param.h>
36#include <iprt/string.h>
37#include <iprt/test.h>
38
39
40/*********************************************************************************************************************************
41* Defined Constants And Macros *
42*********************************************************************************************************************************/
43/** @todo make configurable through cmd line. */
44#define TSTFILEAIO_MAX_REQS_IN_FLIGHT 64
45#define TSTFILEAIO_BUFFER_SIZE (64*_1K)
46
47
48/*********************************************************************************************************************************
49* Global Variables *
50*********************************************************************************************************************************/
51static RTTEST g_hTest = NIL_RTTEST;
52
53
54void tstFileAioTestReadWriteBasic(RTFILE File, bool fWrite, void *pvTestBuf,
55 size_t cbTestBuf, size_t cbTestFile, uint32_t cMaxReqsInFlight)
56{
57 /* Allocate request array. */
58 RTFILEAIOREQ *paReqs;
59 paReqs = (PRTFILEAIOREQ)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(RTFILEAIOREQ));
60 RTTESTI_CHECK_RETV(paReqs);
61 RT_BZERO(paReqs, cMaxReqsInFlight * sizeof(RTFILEAIOREQ));
62
63 /* Allocate array holding pointer to data buffers. */
64 void **papvBuf = (void **)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(void *));
65 RTTESTI_CHECK_RETV(papvBuf);
66
67 /* Allocate the buffers*/
68 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
69 {
70 RTTESTI_CHECK_RC_OK_RETV(RTTestGuardedAlloc(g_hTest, cbTestBuf, PAGE_SIZE, true /*fHead*/, &papvBuf[i]));
71 if (fWrite)
72 memcpy(papvBuf[i], pvTestBuf, cbTestBuf);
73 if (fWrite)
74 memcpy(papvBuf[i], pvTestBuf, cbTestBuf);
75 else
76 RT_BZERO(papvBuf[i], cbTestBuf);
77 }
78
79 /* Allocate array holding completed requests. */
80 RTFILEAIOREQ *paReqsCompleted;
81 paReqsCompleted = (PRTFILEAIOREQ)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(RTFILEAIOREQ));
82 RTTESTI_CHECK_RETV(paReqsCompleted);
83 RT_BZERO(paReqsCompleted, cMaxReqsInFlight * sizeof(RTFILEAIOREQ));
84
85 /* Create a context and associate the file handle with it. */
86 RTFILEAIOCTX hAioContext;
87 RTTESTI_CHECK_RC_RETV(RTFileAioCtxCreate(&hAioContext, cMaxReqsInFlight, 0 /* fFlags */), VINF_SUCCESS);
88 RTTESTI_CHECK_RC_RETV(RTFileAioCtxAssociateWithFile(hAioContext, File), VINF_SUCCESS);
89
90 /* Initialize requests. */
91 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
92 RTFileAioReqCreate(&paReqs[i]);
93
94 RTFOFF off = 0;
95 int cRuns = 0;
96 uint64_t NanoTS = RTTimeNanoTS();
97 size_t cbLeft = cbTestFile;
98 while (cbLeft)
99 {
100 int rc;
101 int cReqs = 0;
102 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
103 {
104 size_t cbTransfer = cbLeft < cbTestBuf ? cbLeft : cbTestBuf;
105 if (!cbTransfer)
106 break;
107
108 if (fWrite)
109 rc = RTFileAioReqPrepareWrite(paReqs[i], File, off, papvBuf[i],
110 cbTransfer, papvBuf[i]);
111 else
112 rc = RTFileAioReqPrepareRead(paReqs[i], File, off, papvBuf[i],
113 cbTransfer, papvBuf[i]);
114 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
115
116 cbLeft -= cbTransfer;
117 off += cbTransfer;
118 cReqs++;
119 }
120
121 rc = RTFileAioCtxSubmit(hAioContext, paReqs, cReqs);
122 RTTESTI_CHECK_MSG(rc == VINF_SUCCESS, ("Failed to submit tasks after %d runs. rc=%Rrc\n", cRuns, rc));
123 if (rc != VINF_SUCCESS)
124 break;
125
126 /* Wait */
127 uint32_t cCompleted = 0;
128 RTTESTI_CHECK_RC(rc = RTFileAioCtxWait(hAioContext, cReqs, RT_INDEFINITE_WAIT,
129 paReqsCompleted, cMaxReqsInFlight, &cCompleted),
130 VINF_SUCCESS);
131 if (rc != VINF_SUCCESS)
132 break;
133
134 if (!fWrite)
135 {
136 for (uint32_t i = 0; i < cCompleted; i++)
137 {
138 /* Compare that we read the right stuff. */
139 void *pvBuf = RTFileAioReqGetUser(paReqsCompleted[i]);
140 RTTESTI_CHECK(pvBuf);
141
142 size_t cbTransfered;
143 RTTESTI_CHECK_RC(rc = RTFileAioReqGetRC(paReqsCompleted[i], &cbTransfered), VINF_SUCCESS);
144 if (rc != VINF_SUCCESS)
145 break;
146 RTTESTI_CHECK_MSG(cbTransfered == cbTestBuf, ("cbTransfered=%zd\n", cbTransfered));
147 RTTESTI_CHECK_RC_OK(rc = (memcmp(pvBuf, pvTestBuf, cbTestBuf) == 0 ? VINF_SUCCESS : VERR_BAD_EXE_FORMAT));
148 if (rc != VINF_SUCCESS)
149 break;
150 memset(pvBuf, 0, cbTestBuf);
151 }
152 }
153 cRuns++;
154 if (RT_FAILURE(rc))
155 break;
156 }
157
158 NanoTS = RTTimeNanoTS() - NanoTS;
159 uint64_t SpeedKBs = (uint64_t)(cbTestFile / (NanoTS / 1000000000.0) / 1024);
160 RTTestValue(g_hTest, "Throughput", SpeedKBs, RTTESTUNIT_KILOBYTES_PER_SEC);
161
162 /* cleanup */
163 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
164 RTTestGuardedFree(g_hTest, papvBuf[i]);
165 RTTestGuardedFree(g_hTest, papvBuf);
166 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
167 RTTESTI_CHECK_RC(RTFileAioReqDestroy(paReqs[i]), VINF_SUCCESS);
168 RTTESTI_CHECK_RC(RTFileAioCtxDestroy(hAioContext), VINF_SUCCESS);
169 RTTestGuardedFree(g_hTest, paReqs);
170}
171
172int main()
173{
174 int rc = RTTestInitAndCreate("tstRTFileAio", &g_hTest);
175 if (rc)
176 return rc;
177
178 /* Check if the API is available. */
179 RTTestSub(g_hTest, "RTFileAioGetLimits");
180 RTFILEAIOLIMITS AioLimits;
181 RT_ZERO(AioLimits);
182 RTTESTI_CHECK_RC(rc = RTFileAioGetLimits(&AioLimits), VINF_SUCCESS);
183 if (RT_SUCCESS(rc))
184 {
185 RTTestSub(g_hTest, "Write");
186 RTFILE hFile;
187 RTFSTYPE enmType;
188 bool fAsyncMayFail = false;
189 rc = RTFsQueryType("tstFileAio#1.tst", &enmType);
190 if ( RT_SUCCESS(rc)
191 && enmType == RTFSTYPE_TMPFS)
192 fAsyncMayFail = true;
193 rc = RTFileOpen(&hFile, "tstFileAio#1.tst",
194 RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_ASYNC_IO);
195 RTTESTI_CHECK( rc == VINF_SUCCESS
196 || ((rc == VERR_ACCESS_DENIED || rc == VERR_INVALID_PARAMETER) && fAsyncMayFail));
197 if (RT_SUCCESS(rc))
198 {
199 uint8_t *pbTestBuf = (uint8_t *)RTTestGuardedAllocTail(g_hTest, TSTFILEAIO_BUFFER_SIZE);
200 for (unsigned i = 0; i < TSTFILEAIO_BUFFER_SIZE; i++)
201 pbTestBuf[i] = i % 256;
202
203 uint32_t cReqsMax = AioLimits.cReqsOutstandingMax < TSTFILEAIO_MAX_REQS_IN_FLIGHT
204 ? AioLimits.cReqsOutstandingMax
205 : TSTFILEAIO_MAX_REQS_IN_FLIGHT;
206
207 /* Basic write test. */
208 RTTestIPrintf(RTTESTLVL_ALWAYS, "Preparing test file, this can take some time and needs quite a bit of harddisk space...\n");
209 tstFileAioTestReadWriteBasic(hFile, true /*fWrite*/, pbTestBuf, TSTFILEAIO_BUFFER_SIZE, 100*_1M, cReqsMax);
210
211 /* Reopen the file before doing the next test. */
212 RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS);
213 if (RTTestErrorCount(g_hTest) == 0)
214 {
215 RTTestSub(g_hTest, "Read/Write");
216 RTTESTI_CHECK_RC(rc = RTFileOpen(&hFile, "tstFileAio#1.tst",
217 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_ASYNC_IO),
218 VINF_SUCCESS);
219 if (RT_SUCCESS(rc))
220 {
221 tstFileAioTestReadWriteBasic(hFile, false /*fWrite*/, pbTestBuf, TSTFILEAIO_BUFFER_SIZE, 100*_1M, cReqsMax);
222 RTFileClose(hFile);
223 }
224 }
225
226 /* Cleanup */
227 RTFileDelete("tstFileAio#1.tst");
228 }
229 else
230 RTTestSkipped(g_hTest, "rc=%Rrc", rc);
231 }
232
233 /*
234 * Summary
235 */
236 return RTTestSummaryAndDestroy(g_hTest);
237}
238
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette