VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstFileAio.cpp@ 23644

Last change on this file since 23644 was 19562, checked in by vboxsync, 16 years ago

Runtime/Aio: Change API again

  • pcReqs in RTFileAioCtxSubmit is useless because it does not specify which request fails. Removed it again and made it possible to get the state of a request through RTFileAioReqGetRC()
  • Introduce request states for the first point and to catch more errors using the API before a system dependent call is made to return the same error codes one every system for the same cause.
  • Add RTFileAioGetLimits to get global limits and indication for AIO support.
  • General cleanups and fixes
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1/* $Id: tstFileAio.cpp 19562 2009-05-10 21:44:16Z vboxsync $ */
2/** @file
3 * IPRT Testcase - File Async I/O.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/file.h>
36#include <iprt/types.h>
37#include <iprt/err.h>
38#include <iprt/string.h>
39#include <iprt/stream.h>
40#include <iprt/mem.h>
41#include <iprt/initterm.h>
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/* Global error counter. */
48int cErrors = 0;
49
50void tstFileAioTestReadWriteBasic(RTFILE File, bool fWrite, void *pvTestBuf, size_t cbTestBuf, size_t cbTestFile, uint32_t cMaxReqsInFlight)
51{
52 int rc = VINF_SUCCESS;
53 RTFILEAIOCTX hAioContext;
54 uint64_t NanoTS = RTTimeNanoTS();
55
56 RTPrintf("tstFileAio: Starting simple %s test...\n", fWrite ? "write" : "read");
57
58 rc = RTFileAioCtxCreate(&hAioContext, cMaxReqsInFlight);
59 if (RT_SUCCESS(rc))
60 {
61 RTFILEAIOREQ *paReqs = NULL;
62 void **papvBuf = NULL;
63 RTFOFF Offset = 0;
64 size_t cbLeft = cbTestFile;
65 int cRun = 0;
66
67 /* Allocate request array. */
68 paReqs = (PRTFILEAIOREQ)RTMemAllocZ(cMaxReqsInFlight * sizeof(RTFILEAIOREQ));
69 if (paReqs)
70 {
71 /* Allocate array holding pointer to data buffers. */
72 papvBuf = (void **)RTMemAllocZ(cMaxReqsInFlight * sizeof(void *));
73 if (papvBuf)
74 {
75 /* Allocate array holding completed requests. */
76 RTFILEAIOREQ *paReqsCompleted = NULL;
77 paReqsCompleted = (PRTFILEAIOREQ)RTMemAllocZ(cMaxReqsInFlight * sizeof(RTFILEAIOREQ));
78 if (paReqsCompleted)
79 {
80 /* Associate file with context.*/
81 rc = RTFileAioCtxAssociateWithFile(hAioContext, File);
82 if (RT_SUCCESS(rc))
83 {
84 /* Initialize buffers. */
85 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
86 {
87 papvBuf[i] = RTMemPageAllocZ(cbTestBuf);
88
89 if (fWrite)
90 memcpy(papvBuf[i], pvTestBuf, cbTestBuf);
91 }
92
93 /* Initialize requests. */
94 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
95 RTFileAioReqCreate(&paReqs[i]);
96
97 while (cbLeft)
98 {
99 int cReqs = 0;
100
101 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
102 {
103 size_t cbTransfer = (cbLeft < cbTestBuf) ? cbLeft : cbTestBuf;
104
105 if (!cbTransfer)
106 break;
107
108 if (fWrite)
109 rc = RTFileAioReqPrepareWrite(paReqs[i], File, Offset, papvBuf[i],
110 cbTransfer, papvBuf[i]);
111 else
112 rc = RTFileAioReqPrepareRead(paReqs[i], File, Offset, papvBuf[i],
113 cbTransfer, papvBuf[i]);
114
115 cbLeft -= cbTransfer;
116 Offset += cbTransfer;
117 cReqs++;
118 }
119
120 rc = RTFileAioCtxSubmit(hAioContext, paReqs, cReqs);
121 if (RT_FAILURE(rc))
122 {
123 RTPrintf("tstFileAio: FATAL ERROR - Failed to submit tasks after %d runs. rc=%Rrc\n", cRun, rc);
124 cErrors++;
125 break;
126 }
127
128 /* Wait */
129 uint32_t cCompleted = 0;
130 rc = RTFileAioCtxWait(hAioContext, cReqs, RT_INDEFINITE_WAIT,
131 paReqsCompleted, cMaxReqsInFlight,
132 &cCompleted);
133 if (RT_FAILURE(rc))
134 {
135 RTPrintf("tstFileAio: FATAL ERROR - Waiting failed. rc=%Rrc\n", rc);
136 cErrors++;
137 break;
138 }
139
140 if (!fWrite)
141 {
142 for (uint32_t i = 0; i < cCompleted; i++)
143 {
144 /* Compare that we read the right stuff. */
145 void *pvBuf = RTFileAioReqGetUser(paReqsCompleted[i]);
146
147 size_t cbTransfered;
148 int rcReq = RTFileAioReqGetRC(paReqsCompleted[i], &cbTransfered);
149 if (RT_FAILURE(rcReq) || (cbTransfered != cbTestBuf))
150 {
151 RTPrintf("tstFileAio: FATAL ERROR - Request %d failed with rc=%Rrc cbTransfered=%d.\n",
152 i, rcReq, cbTransfered);
153 cErrors++;
154 rc = rcReq;
155 break;
156 }
157
158 if (memcmp(pvBuf, pvTestBuf, cbTestBuf) != 0)
159 {
160 RTPrintf("tstFileAio: FATAL ERROR - Unexpected content in memory.\n");
161 cErrors++;
162 break;
163 }
164 memset(pvBuf, 0, cbTestBuf);
165 }
166 }
167 cRun++;
168 if (RT_FAILURE(rc))
169 break;
170 }
171
172 /* Free buffers. */
173 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
174 RTMemPageFree(papvBuf[i]);
175
176 /* Free requests. */
177 for (unsigned i = 0; i < cMaxReqsInFlight; i++)
178 {
179 rc = RTFileAioReqDestroy(paReqs[i]);
180 if (RT_FAILURE(rc))
181 {
182 RTPrintf("tstFileAio: ERROR - Failed to destroy request %d. rc=%Rrc\n", i, rc);
183 cErrors++;
184 }
185 }
186
187 NanoTS = RTTimeNanoTS() - NanoTS;
188 unsigned SpeedKBs = cbTestFile / (NanoTS / 1000000000.0) / 1024;
189
190 RTPrintf("tstFileAio: Completed simple %s test: %d.%03d MB/sec\n",
191 fWrite ? "write" : "read",
192 SpeedKBs / 1000,
193 SpeedKBs % 1000);
194 }
195 else
196 {
197 RTPrintf("tstFileAio: FATAL ERROR - Failed to asssociate file with async I/O context. rc=%Rrc\n", rc);
198 cErrors++;
199 }
200 }
201 else
202 {
203 RTPrintf("tstFileAio: FATAL ERROR - Failed to allocate memory for completed request array.\n");
204 cErrors++;
205 }
206 RTMemFree(papvBuf);
207 }
208 else
209 {
210 RTPrintf("tstFileAio: FATAL ERROR - Failed to allocate memory for buffer array.\n");
211 cErrors++;
212 }
213 RTMemFree(paReqs);
214 }
215 else
216 {
217 RTPrintf("tstFileAio: FATAL ERROR - Failed to allocate memory for request array.\n");
218 cErrors++;
219 }
220
221 rc = RTFileAioCtxDestroy(hAioContext);
222 if (RT_FAILURE(rc))
223 {
224 RTPrintf("tstFileAio: FATAL ERROR - Failed to destroy async I/O context. rc=%Rrc\n", rc);
225 cErrors++;
226 }
227 }
228 else
229 {
230 RTPrintf("tstFileAio: FATAL ERROR - Failed to create async I/O context. rc=%Rrc\n", rc);
231 cErrors++;
232 }
233}
234
235int main()
236{
237 RTPrintf("tstFileAio: TESTING\n");
238 RTR3Init();
239
240 /* Check if the API is available. */
241 RTFILEAIOLIMITS AioLimits;
242
243 memset(&AioLimits, 0, sizeof(AioLimits));
244 int rc = RTFileAioGetLimits(&AioLimits);
245 if (RT_FAILURE(rc))
246 {
247 if (rc == VERR_NOT_SUPPORTED)
248 RTPrintf("tstFileAio: FATAL ERROR - File AIO API not available\n");
249 else
250 RTPrintf("tstFileAio: FATAL ERROR - Unexpected error rc=%Rrc\n", rc);
251 return 1;
252 }
253
254 RTFILE File;
255 void *pvTestBuf = NULL;
256 rc = RTFileOpen(&File, "tstFileAio#1.tst", RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_ASYNC_IO);
257 if (RT_FAILURE(rc))
258 {
259 RTPrintf("tstFileAio: FATAL ERROR - Failed to open file #1. rc=%Rrc\n", rc);
260 return 1;
261 }
262
263 pvTestBuf = RTMemAllocZ(64 * _1K);
264 for (unsigned i = 0; i < 64*_1K; i++)
265 ((char *)pvTestBuf)[i] = i % 256;
266
267 uint32_t cReqsMax = AioLimits.cReqsOutstandingMax < TSTFILEAIO_MAX_REQS_IN_FLIGHT
268 ? AioLimits.cReqsOutstandingMax
269 : TSTFILEAIO_MAX_REQS_IN_FLIGHT;
270
271 /* Basic write test. */
272 RTPrintf("tstFileAio: Preparing test file, this can take some time and needs quite a bit of harddisk\n");
273 tstFileAioTestReadWriteBasic(File, true, pvTestBuf, 64*_1K, 100*_1M, cReqsMax);
274 /* Reopen the file. */
275 RTFileClose(File);
276 rc = RTFileOpen(&File, "tstFileAio#1.tst", RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_ASYNC_IO);
277 if (RT_SUCCESS(rc))
278 {
279 tstFileAioTestReadWriteBasic(File, false, pvTestBuf, 64*_1K, 100*_1M, cReqsMax);
280 RTFileClose(File);
281 }
282 else
283 {
284 RTPrintf("tstFileAio: FATAL ERROR - Failed to open file #1. rc=%Rrc\n", rc);
285 cErrors++;
286 }
287
288 /* Cleanup */
289 RTMemFree(pvTestBuf);
290 RTFileDelete("tstFileAio#1.tst");
291 /*
292 * Summary
293 */
294 if (cErrors == 0)
295 RTPrintf("tstFileAio: SUCCESS\n");
296 else
297 RTPrintf("tstFileAio: FAILURE - %d errors\n", cErrors);
298 return !!cErrors;
299}
300
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