1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/f32test/concur/t_cfsbench.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1086 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Do benchmarking comparisons in asynchronous and synchronous modes.
1.18 +//
1.19 +//
1.20 +
1.21 +//! @file f32test\concur\t_cfsbench.cpp
1.22 +
1.23 +#include <f32file.h>
1.24 +#include <e32test.h>
1.25 +#include <f32dbg.h>
1.26 +#include "t_server.h"
1.27 +#include "t_tdebug.h"
1.28 +
1.29 +// The following #defines are for using older (and less accurate) benchmark
1.30 +// timings. They use multiple threads to get the operations simultaneous
1.31 +// but this is inherrently inaccurate (it depends whether one of them starts
1.32 +// and/or ends before the other how accurate the timings are). If you leave
1.33 +// them both commented out then the tests will be done in a single thread
1.34 +// using asynchronous file operations, thus avoiding the problem.
1.35 +
1.36 +// Uncomment the following if you want to test asynchronous file operations
1.37 +// using two threads rather than in a single thread.
1.38 +
1.39 +// #define TEST_ASYNC_IN_THREAD
1.40 +
1.41 +// Uncomment the following if you want to test using synchronous file
1.42 +// operations, using two threads to do both at once.
1.43 +
1.44 +// #define TEST_SYNC_IN_THREAD
1.45 +
1.46 +struct TStats
1.47 +//
1.48 +// Statistics -- size and time of operations.
1.49 +//
1.50 + {
1.51 + TInt64 iSize;
1.52 + TInt64 iTime;
1.53 + void Init() { iSize = 0; iTime = 0; }
1.54 + };
1.55 +
1.56 +GLDEF_D RTest test(_L("T_CFSBENCH"));
1.57 +GLDEF_D RFs TheFs;
1.58 +
1.59 +LOCAL_D TFullName gFsName;
1.60 +LOCAL_D TFullName gFsName1;
1.61 +LOCAL_D TFullName gFsName2;
1.62 +LOCAL_D TFullName gOldFsName;
1.63 +LOCAL_D TFullName gNewFsName;
1.64 +LOCAL_D TBool gNoMedia = ETrue;
1.65 +
1.66 +#if defined(TEST_SYNC_IN_THREAD) || defined(TEST_ASYNC_IN_THREAD)
1.67 +LOCAL_D TInt gThreadNumber = 0;
1.68 +#endif
1.69 +
1.70 +LOCAL_D RMutex gDataLock;
1.71 +LOCAL_D TStats gWrStats;
1.72 +LOCAL_D TStats gRdStats;
1.73 +
1.74 +_LIT(KFsFile, "CFAFSDLY");
1.75 +_LIT(KFsName, "DelayFS");
1.76 +
1.77 +LOCAL_D const TInt32 KSecond = 1000000;
1.78 +LOCAL_D const TInt32 KTimeBM = 20;
1.79 +LOCAL_D const TInt32 KNumBuf = 100;
1.80 +LOCAL_D const TInt32 KBufLen = 0x100;
1.81 +LOCAL_D const TInt32 KMaxThr = 10;
1.82 +LOCAL_D const TInt32 KMaxLag = 4;
1.83 +
1.84 +LOCAL_D TBuf8<KBufLen> gBufferArr[KMaxThr][KNumBuf];
1.85 +LOCAL_D TRequestStatus gStatusArr[KMaxThr][KNumBuf];
1.86 +
1.87 +LOCAL_C void AddStats(TStats& aStats, TInt64 aSize, TInt64 aTime)
1.88 +/// Add values to the statistics.
1.89 + {
1.90 + gDataLock.Wait();
1.91 + aStats.iSize += aSize;
1.92 + aStats.iTime += aTime;
1.93 + gDataLock.Signal();
1.94 + }
1.95 +
1.96 +LOCAL_C TInt GetSpeed(TStats& aStats)
1.97 +/// Calculate and return the data throughput from the statistics, rounded.
1.98 + {
1.99 + gDataLock.Wait();
1.100 + TInt speed = I64LOW((aStats.iSize + aStats.iTime/2) / aStats.iTime);
1.101 + gDataLock.Signal();
1.102 + return speed;
1.103 + }
1.104 +
1.105 +LOCAL_C TInt32 GetSpeed(TInt aOps, TInt64 aDtime)
1.106 +/// Calculate and return the throughput from the umber of blocks transferred
1.107 +/// and the elapsed time.
1.108 + {
1.109 + TInt64 dsize = MAKE_TINT64(0, aOps) * MAKE_TINT64(0, KBufLen) * MAKE_TINT64(0, KSecond);
1.110 + TInt32 speed = I64LOW((dsize + aDtime/2) / aDtime);
1.111 + return speed;
1.112 + }
1.113 +
1.114 +LOCAL_C TBool DriveIsOK(TChar c)
1.115 +/// Test that a selected drive leter is OK to write files.
1.116 + {
1.117 + TInt r;
1.118 + TInt drv;
1.119 + r=TheFs.CharToDrive(c, drv);
1.120 + if (r != KErrNone)
1.121 + return EFalse;
1.122 + TDriveInfo info;
1.123 + r=TheFs.Drive(info,drv);
1.124 + test(r==KErrNone);
1.125 + return (info.iDriveAtt != 0 && !(info.iDriveAtt & KDriveAttRom));
1.126 + }
1.127 +
1.128 +LOCAL_C TChar MountTestFileSystem(TInt aDrive)
1.129 +//
1.130 +// Mount a new CTestFileSystem on the drive under test
1.131 +//
1.132 + {
1.133 + TInt r;
1.134 + TBuf<64> b;
1.135 + TChar c;
1.136 + r=TheFs.DriveToChar(aDrive,c);
1.137 + test(r==KErrNone);
1.138 + b.Format(_L("Mount test file system on %c:"),(TUint)c);
1.139 + test.Next(b);
1.140 +
1.141 + r=TheFs.AddFileSystem(KFsFile);
1.142 + test(r==KErrNone || r==KErrAlreadyExists);
1.143 +
1.144 + r=TheFs.FileSystemName(gOldFsName,aDrive);
1.145 + test(r==KErrNone || r==KErrNotFound);
1.146 +
1.147 + TDriveInfo drv;
1.148 + r = TheFs.Drive(drv, aDrive);
1.149 + test(r == KErrNone);
1.150 +
1.151 + gNoMedia = (drv.iType == EMediaUnknown || drv.iType == EMediaNotPresent);
1.152 +
1.153 + if (gOldFsName.Length() > 0)
1.154 + {
1.155 + TTest::Printf(_L("Dismount %C: %S"), (TUint)c, &gOldFsName);
1.156 + r=TheFs.DismountFileSystem(gOldFsName,aDrive);
1.157 + test(r==KErrNone);
1.158 + }
1.159 +
1.160 + r=TheFs.MountFileSystem(KFsName,aDrive);
1.161 + test(r==KErrNone);
1.162 +
1.163 + r=TheFs.FileSystemName(gNewFsName,aDrive);
1.164 + test(r==KErrNone);
1.165 + test(gNewFsName.CompareF(KFsName)==0);
1.166 + return c;
1.167 + }
1.168 +
1.169 +LOCAL_C void UnmountFileSystem(TInt aDrive)
1.170 +/// Unmount a test filesystem and mount the old one.
1.171 + {
1.172 + TChar c;
1.173 + TInt r=TheFs.DriveToChar(aDrive,c);
1.174 + test(r==KErrNone);
1.175 + r=TheFs.DismountFileSystem(gNewFsName,aDrive);
1.176 + test(r==KErrNone);
1.177 + // if there's no media present, don't try to mount it
1.178 + if (gNoMedia)
1.179 + {
1.180 + test.Printf(_L("No media on %C: so don't remount it"), (TUint)c);
1.181 + }
1.182 + else if (gOldFsName.Length() > 0)
1.183 + {
1.184 + test.Printf(_L("Mount %C: %S"), (TUint)c, &gOldFsName);
1.185 + r=TheFs.MountFileSystem(gOldFsName,aDrive);
1.186 + test(r==KErrNone);
1.187 + }
1.188 + if (r != KErrNone)
1.189 + test.Printf(_L("Error %d remounting %S on %C\n"), r, &gOldFsName, (TUint)c);
1.190 + }
1.191 +
1.192 +LOCAL_C void RemountFileSystem(TInt aDrive, TBool aSync)
1.193 +/// Unmount and remount the file system on the specified drive in the
1.194 +/// selected mode.
1.195 +/// @param aDrive Drive number (EDriveC etc.).
1.196 +/// @param aSync Mount synchronous if true, asynchronous if not.
1.197 + {
1.198 + TChar c;
1.199 + TInt r=TheFs.DriveToChar(aDrive,c);
1.200 + r=TheFs.FileSystemName(gFsName, aDrive);
1.201 + test(r==KErrNone || r==KErrNotFound);
1.202 +
1.203 + if (gFsName.Length() > 0)
1.204 + {
1.205 + r=TheFs.DismountFileSystem(gFsName, aDrive);
1.206 + if(r!=KErrNone)
1.207 + {
1.208 + test.Printf(_L("Error = %d"),r);
1.209 + test(EFalse);
1.210 + }
1.211 + }
1.212 +
1.213 + TBufC<16> type = _L("asynchronous");
1.214 + if (aSync)
1.215 + type = _L("synchronous");
1.216 + test.Printf(_L("Mount filesystem %c: %-8S as %S\n"), (TUint)c, &gFsName, &type);
1.217 +
1.218 +#ifdef __CONCURRENT_FILE_ACCESS__
1.219 + r=TheFs.MountFileSystem(gFsName, aDrive, aSync);
1.220 +#else
1.221 + r=TheFs.MountFileSystem(gFsName, aDrive);
1.222 +#endif
1.223 +
1.224 + test(r==KErrNone);
1.225 + }
1.226 +
1.227 +enum TOper
1.228 + {
1.229 + ERead,
1.230 + EWrite
1.231 + };
1.232 +
1.233 +// ---------------------------------------------------------------------------
1.234 +
1.235 +#if defined(TEST_SYNC_IN_THREAD)
1.236 +
1.237 +LOCAL_C TInt testSyncAccess(TAny* aData)
1.238 +///
1.239 +/// Test read file handling.
1.240 +///
1.241 +/// @param aData pointer to the thread data area
1.242 + {
1.243 + TThreadData& data = *(TThreadData*)aData;
1.244 + TFileName fileName = data.iFile;
1.245 + TBool dowrite = (data.iData != NULL);
1.246 +
1.247 + RFs myFs;
1.248 + TInt r = myFs.Connect();
1.249 + TEST(r==KErrNone);
1.250 +
1.251 + r = myFs.SetSessionPath(gSessionPath);
1.252 + if (r != KErrNone)
1.253 + TTest::Fail(HERE, _L("SetSessionPath returned %d"), r);
1.254 +
1.255 + TVolumeInfo vol;
1.256 + TInt drv;
1.257 + r = myFs.CharToDrive(fileName[0], drv);
1.258 + if (r != KErrNone)
1.259 + TTest::Fail(HERE, _L("CharToDrive(%c) returned %d"), fileName[0], r);
1.260 + r = myFs.Volume(vol, drv);
1.261 + if (r != KErrNone)
1.262 + TTest::Fail(HERE, _L("Volume() returned %d"), r);
1.263 +
1.264 + TInt maxwrite = TInt(vol.iFree / 2 - KBufLen);
1.265 + if (maxwrite < KBufLen*2)
1.266 + TTest::Fail(HERE, _L("Not enough space to do test, only %d KB available"),
1.267 + TInt(vol.iFree/1024));
1.268 +
1.269 + RFile f;
1.270 + RTimer timer;
1.271 + TTime startTime;
1.272 + TTime endTime;
1.273 + TTimeIntervalMicroSeconds timeTaken;
1.274 +
1.275 + TBuf8<KBufLen> buff;
1.276 + TRequestStatus tstat;
1.277 +
1.278 + TInt wrnum = 0;
1.279 + TInt rdnum = 0;
1.280 +
1.281 + timer.CreateLocal();
1.282 +
1.283 + if (dowrite)
1.284 + {
1.285 + // write tests
1.286 +
1.287 + r = f.Replace(myFs, fileName, EFileStreamText | EFileWrite);
1.288 + TEST(r==KErrNone);
1.289 +
1.290 + // wait for both tasks to have a chance to complete opening the files
1.291 + User::After(1000);
1.292 +
1.293 + buff.Fill('_', KBufLen);
1.294 +
1.295 + timer.After(tstat, KTimeBM * KSecond);
1.296 +
1.297 + startTime.HomeTime();
1.298 +
1.299 + while (tstat == KRequestPending)
1.300 + {
1.301 + TInt pos = (wrnum * KBufLen) % maxwrite;
1.302 + r = f.Write(pos, buff);
1.303 + TEST(r==KErrNone);
1.304 + ++wrnum;
1.305 + }
1.306 +
1.307 + endTime.HomeTime();
1.308 + timeTaken=endTime.MicroSecondsFrom(startTime);
1.309 +
1.310 + TInt64 dtime = timeTaken.Int64();
1.311 + TInt64 dsize = wrnum * KBufLen * TInt64(KSecond);
1.312 + TInt32 speed = TInt32((dsize + dtime/2) / dtime);
1.313 + AddStats(gWrStats, dsize, dtime);
1.314 +
1.315 + TTest::Printf(_L("%8d writes in %6d mS = %8d bytes per second\n"),
1.316 + wrnum, TInt32(dtime)/1000, speed);
1.317 +
1.318 + timer.Cancel();
1.319 + f.Close();
1.320 + }
1.321 + else
1.322 + {
1.323 + // read tests
1.324 +
1.325 + r = f.Open(myFs, fileName, EFileStreamText);
1.326 + TEST(r==KErrNone);
1.327 +
1.328 + // wait for both tasks to have a chance to complete opening the files
1.329 + User::After(1000);
1.330 +
1.331 + timer.After(tstat, KTimeBM * KSecond);
1.332 +
1.333 + startTime.HomeTime();
1.334 +
1.335 + while (tstat == KRequestPending)
1.336 + {
1.337 + TInt pos = (rdnum * KBufLen) % maxwrite;
1.338 + r = f.Read(pos, buff, KBufLen);
1.339 + TEST(r==KErrNone);
1.340 + ++rdnum;
1.341 + }
1.342 +
1.343 + endTime.HomeTime();
1.344 + timeTaken=endTime.MicroSecondsFrom(startTime);
1.345 +
1.346 + TInt64 dtime = timeTaken.Int64();
1.347 + TInt64 dsize = rdnum * KBufLen * TInt64(KSecond);
1.348 + TInt32 speed = TInt32((dsize + dtime/2) / dtime);
1.349 + AddStats(gRdStats, dsize, dtime);
1.350 +
1.351 + // wait to allow the dust to settle
1.352 + User::After(KSecond);
1.353 +
1.354 + TTest::Printf(_L("%8d reads in %6d mS = %8d bytes per second\n"),
1.355 + rdnum, TInt32(dtime)/1000, speed);
1.356 +
1.357 + timer.Cancel();
1.358 + timer.Close();
1.359 + f.Close();
1.360 +
1.361 + // delete file after reading it
1.362 + myFs.Delete(fileName);
1.363 + }
1.364 +
1.365 + myFs.Close();
1.366 + return r;
1.367 + }
1.368 +
1.369 +#endif
1.370 +
1.371 +// ---------------------------------------------------------------------------
1.372 +
1.373 +#if defined(TEST_ASYNC_IN_THREAD)
1.374 +
1.375 +LOCAL_C TInt testAsyncAccess(TAny* aData)
1.376 +//
1.377 +/// Test read file handling.
1.378 +///
1.379 +/// @param aData pointer to the thread data area
1.380 + {
1.381 + TThreadData& data = *(TThreadData*)aData;
1.382 + TFileName fileName = data.iFile;
1.383 + TBool dowrite = (data.iData != NULL);
1.384 + TBuf8<KBufLen>* buffer = gBufferArr[data.iNum];
1.385 + TRequestStatus* status = gStatusArr[data.iNum];
1.386 +
1.387 + RFs myFs;
1.388 + TInt r = myFs.Connect();
1.389 + TEST(r==KErrNone);
1.390 +
1.391 + r = myFs.SetSessionPath(gSessionPath);
1.392 + if (r != KErrNone)
1.393 + TTest::Fail(HERE, _L("SetSessionPath returned %d"), r);
1.394 +
1.395 + TVolumeInfo vol;
1.396 + TInt drv;
1.397 + r = myFs.CharToDrive(fileName[0], drv);
1.398 + if (r != KErrNone)
1.399 + TTest::Fail(HERE, _L("CharToDrive(%c) returned %d"), fileName[0], r);
1.400 + r = myFs.Volume(vol, drv);
1.401 + if (r != KErrNone)
1.402 + TTest::Fail(HERE, _L("Volume() returned %d"), r);
1.403 +
1.404 + TInt64 maxwrite = vol.iFree / 2 - KBufLen;
1.405 + if (maxwrite < KBufLen*2)
1.406 + TTest::Fail(HERE, _L("Not enough space to do test, only %d KB available"),
1.407 + TInt(vol.iFree/1024));
1.408 +
1.409 + RFile f;
1.410 + RTimer timer;
1.411 + TRequestStatus tstat;
1.412 + TTime startTime;
1.413 + TTime endTime;
1.414 + TTimeIntervalMicroSeconds timeTaken;
1.415 +
1.416 + TInt wrnum = 0;
1.417 + TInt rdnum = 0;
1.418 + TInt opnum = 0;
1.419 + TInt opfin = 0;
1.420 + TInt i;
1.421 +
1.422 + timer.CreateLocal();
1.423 +
1.424 + if (dowrite)
1.425 + {
1.426 + r = f.Replace(myFs, fileName, EFileStreamText | EFileWrite);
1.427 + TEST(r==KErrNone);
1.428 +
1.429 + // wait for both tasks to have a chance to complete opening the files
1.430 + User::After(1000);
1.431 +
1.432 + for (i = 0; i < KNumBuf; i++)
1.433 + buffer[i].Fill('_', KBufLen);
1.434 +
1.435 + timer.After(tstat, KTimeBM * KSecond);
1.436 +
1.437 + startTime.HomeTime();
1.438 +
1.439 + while (tstat == KRequestPending)
1.440 + {
1.441 + TInt pos = TInt((wrnum * KBufLen) % maxwrite);
1.442 + TInt bnum = opnum++ % KNumBuf;
1.443 + f.Write(pos, buffer[bnum], status[bnum]);
1.444 + if (opnum - opfin > KMaxLag)
1.445 + {
1.446 + while (status[opfin % KNumBuf] == KRequestPending)
1.447 + User::WaitForRequest(status[opfin % KNumBuf]);
1.448 + opfin++;
1.449 + }
1.450 + ++wrnum;
1.451 + }
1.452 +
1.453 + while (opfin < opnum)
1.454 + {
1.455 + while (status[opfin % KNumBuf] == KRequestPending)
1.456 + User::WaitForRequest(status[opfin % KNumBuf]);
1.457 + opfin++;
1.458 + }
1.459 +
1.460 + endTime.HomeTime();
1.461 + TTimeIntervalMicroSeconds timeTaken=endTime.MicroSecondsFrom(startTime);
1.462 +
1.463 + TInt64 dtime = timeTaken.Int64();
1.464 + TInt64 dsize = wrnum * KBufLen * TInt64(KSecond);
1.465 + TInt32 speed = TInt32((dsize + dtime/2) / dtime);
1.466 + AddStats(gWrStats, dsize, dtime);
1.467 +
1.468 + TTest::Printf(_L("%8d writes in %6d mS = %8d bytes per second\n"),
1.469 + wrnum, TInt32(dtime)/1000, speed);
1.470 + }
1.471 + else
1.472 + {
1.473 + r = f.Open(myFs, fileName, EFileStreamText);
1.474 + TEST(r==KErrNone);
1.475 +
1.476 + timer.After(tstat, KTimeBM * KSecond);
1.477 +
1.478 + startTime.HomeTime();
1.479 +
1.480 + while (tstat == KRequestPending)
1.481 + {
1.482 + TInt pos = TInt((rdnum * KBufLen) % maxwrite);
1.483 + TInt bnum = opnum++ % KNumBuf;
1.484 + f.Read(pos, buffer[bnum], status[bnum]);
1.485 + if (opnum - opfin > KMaxLag)
1.486 + {
1.487 + User::WaitForRequest(status[opfin++ % KNumBuf]);
1.488 + }
1.489 + ++rdnum;
1.490 + }
1.491 +
1.492 + while (opfin < opnum)
1.493 + {
1.494 + if (status[opfin % KNumBuf] == KRequestPending)
1.495 + User::WaitForRequest(status[opfin % KNumBuf]);
1.496 + opfin++;
1.497 + }
1.498 +
1.499 + endTime.HomeTime();
1.500 + timeTaken=endTime.MicroSecondsFrom(startTime);
1.501 + TInt64 dtime = timeTaken.Int64();
1.502 + TInt64 dsize = rdnum * KBufLen * TInt64(KSecond);
1.503 + TInt32 speed = TInt32((dsize + dtime/2) / dtime);
1.504 + AddStats(gRdStats, dsize, dtime);
1.505 +
1.506 + // wait to allow the dust to settle
1.507 + User::After(KSecond);
1.508 +
1.509 + TTest::Printf(_L("%8d reads in %6d mS = %8d bytes per second\n"),
1.510 + rdnum, TInt32(dtime)/1000, speed);
1.511 +
1.512 + myFs.Delete(fileName);
1.513 + }
1.514 +
1.515 + timer.Cancel();
1.516 + timer.Close();
1.517 + f.Close();
1.518 + myFs.Close();
1.519 + return r;
1.520 + }
1.521 +
1.522 +#endif
1.523 +
1.524 +// ---------------------------------------------------------------------------
1.525 +
1.526 +class TFileOps
1.527 +/// Do operations on a file.
1.528 + {
1.529 +public:
1.530 + TFileOps();
1.531 + TInt Open(TChar dr, TInt n);
1.532 + TInt Close();
1.533 + TInt Reset();
1.534 + TInt Erase();
1.535 + TInt Write();
1.536 + TInt Read();
1.537 + TInt End();
1.538 +public:
1.539 + TFileName iName;
1.540 + RFile iF;
1.541 + TBuf8<KBufLen> iBuffer[KMaxLag];
1.542 + TRequestStatus iStatus[KMaxLag];
1.543 + TInt iPtr;
1.544 + TInt iNum;
1.545 + TInt iOps;
1.546 + TInt iMax;
1.547 + TBool iOpen;
1.548 + };
1.549 +
1.550 +TFileOps::TFileOps() : iPtr(0), iNum(0), iOps(0), iMax(0), iOpen(EFalse)
1.551 + {
1.552 + for (TInt i = 0; i < KMaxLag; i++)
1.553 + {
1.554 + iStatus[i] = KErrNone;
1.555 + iBuffer[i].Fill(TChar('_'), KBufLen);
1.556 + }
1.557 + }
1.558 +
1.559 +TInt TFileOps::Open(TChar aDrvCh, TInt aNum)
1.560 +/// Open the file for testing, give error if there is not enough space for it.
1.561 +/// @param aDrvCh Drive letter.
1.562 +/// @param aNum File number suffix.
1.563 + {
1.564 + TVolumeInfo vol;
1.565 + TInt drv;
1.566 + TInt r = TheFs.CharToDrive(aDrvCh, drv);
1.567 + if (r != KErrNone)
1.568 + TTest::Fail(HERE, _L("CharToDrive(%c) returned %d"), (TUint)aDrvCh, r);
1.569 + r = TheFs.Volume(vol, drv);
1.570 + if (r != KErrNone)
1.571 + TTest::Fail(HERE, _L("Volume(%c:) returned %d"), (TUint)aDrvCh, r);
1.572 +
1.573 + iMax = I64LOW(vol.iFree / MAKE_TINT64(0,KBufLen)) / 2 - 1;
1.574 + if (iMax < 10)
1.575 + TTest::Fail(HERE, _L("Not enough space to do test, only %d KB available"),
1.576 + I64LOW(vol.iFree/1024));
1.577 +
1.578 + Reset();
1.579 + iName.Format(_L("%c:\\TEST_%d"), (TUint)aDrvCh, aNum);
1.580 + r = iF.Replace(TheFs, iName, EFileStreamText | EFileWrite);
1.581 + if (r == KErrNone)
1.582 + iOpen = ETrue;
1.583 + return r;
1.584 + }
1.585 +
1.586 +TInt TFileOps::Close()
1.587 +/// Close and delete the file, returning the number of operations done.
1.588 + {
1.589 + if (!iOpen)
1.590 + return 0;
1.591 + iF.Close();
1.592 + TheFs.Delete(iName);
1.593 + iOpen = EFalse;
1.594 + return iNum;
1.595 + }
1.596 +
1.597 +TInt TFileOps::Reset()
1.598 +/// Reset all of the counts.
1.599 + {
1.600 + iPtr = 0;
1.601 + iNum = 0;
1.602 + iOps = 0;
1.603 + return 0;
1.604 + }
1.605 +
1.606 +TInt TFileOps::Write()
1.607 +/// If there is a free buffer available, start a write.
1.608 + {
1.609 + if (!iOpen)
1.610 + return 0;
1.611 + while (iNum < iOps && iStatus[iNum%KMaxLag] != KRequestPending)
1.612 + iNum++;
1.613 + if (iOps < KMaxLag || iStatus[iPtr] != KRequestPending)
1.614 + {
1.615 + TInt pos = iNum%iMax * KBufLen;
1.616 + iF.Write(pos, iBuffer[iPtr], iStatus[iPtr]);
1.617 + iOps++;
1.618 + iPtr++;
1.619 + iPtr %= KMaxLag;
1.620 + return 1;
1.621 + }
1.622 + return 0;
1.623 + }
1.624 +
1.625 +TInt TFileOps::Read()
1.626 +/// If there is a free buffer available, start a read.
1.627 + {
1.628 + if (!iOpen)
1.629 + return 0;
1.630 + while (iNum < iOps && iStatus[iNum%KMaxLag] != KRequestPending)
1.631 + iNum++;
1.632 + if (iOps < KMaxLag || iStatus[iPtr] != KRequestPending)
1.633 + {
1.634 + TInt pos = iNum%iMax * KBufLen;
1.635 + iF.Read(pos, iBuffer[iPtr], iStatus[iPtr]);
1.636 + iOps++;
1.637 + iPtr++;
1.638 + iPtr %= KMaxLag;
1.639 + return 1;
1.640 + }
1.641 + return 0;
1.642 + }
1.643 +
1.644 +TInt TFileOps::End()
1.645 +/// Wait until all outstanding operations have ended, then return the number.
1.646 + {
1.647 + if (!iOpen)
1.648 + return 0;
1.649 + while (iNum < iOps)
1.650 + {
1.651 + if (iStatus[iNum%KMaxLag] == KRequestPending)
1.652 + User::WaitForRequest(iStatus[iNum%KMaxLag]);
1.653 + else
1.654 + iNum++;
1.655 + }
1.656 + if (iOps < iMax)
1.657 + iMax = iOps;
1.658 + return iNum;
1.659 + }
1.660 +
1.661 +LOCAL_C TInt testAsyncAccess(TChar dc1, TChar dc2)
1.662 +//
1.663 +// Test one drive against the other.
1.664 +//
1.665 + {
1.666 + TFileOps f1;
1.667 + TFileOps f2;
1.668 +
1.669 + f1.Open(dc1, 1);
1.670 + if (dc1 != dc2)
1.671 + f2.Open(dc2, 2);
1.672 +
1.673 + TInt op1 = 0;
1.674 + TInt op2 = 0;
1.675 + RTimer timer;
1.676 + TRequestStatus tstat;
1.677 + TTime startTime;
1.678 + TTime endTime;
1.679 + TTimeIntervalMicroSeconds timeTaken;
1.680 +
1.681 + timer.CreateLocal();
1.682 +
1.683 + timer.After(tstat, KTimeBM * KSecond);
1.684 +
1.685 + startTime.HomeTime();
1.686 +
1.687 + while (tstat == KRequestPending)
1.688 + {
1.689 + TInt num = f1.Write();
1.690 + num += f2.Write();
1.691 + if (num == 0)
1.692 + User::WaitForAnyRequest();
1.693 + }
1.694 +
1.695 + op1 = f1.End();
1.696 + op2 = f2.End();
1.697 +
1.698 + endTime.HomeTime();
1.699 + timeTaken=endTime.MicroSecondsFrom(startTime);
1.700 +
1.701 + TInt64 dtime = timeTaken.Int64();
1.702 +
1.703 + TTest::Printf(_L("%c: %8d writes in %6d mS = %8d bytes per second\n"),
1.704 + (TUint)dc1, op1, I64LOW(dtime)/1000, GetSpeed(op1, dtime));
1.705 +
1.706 + if (dc1 != dc2)
1.707 + TTest::Printf(_L("%c: %8d writes in %6d mS = %8d bytes per second\n"),
1.708 + (TUint)dc2, op2, I64LOW(dtime)/1000, GetSpeed(op2, dtime));
1.709 +
1.710 + AddStats(gWrStats, MAKE_TINT64(0, op1 + op2) * MAKE_TINT64(0, KBufLen) * MAKE_TINT64(0, KSecond), dtime);
1.711 +
1.712 + // now the reads!
1.713 +
1.714 + f1.Reset();
1.715 + f2.Reset();
1.716 +
1.717 + timer.After(tstat, KTimeBM * KSecond);
1.718 +
1.719 + startTime.HomeTime();
1.720 +
1.721 + while (tstat == KRequestPending)
1.722 + {
1.723 + f1.Read();
1.724 + f2.Read();
1.725 + User::WaitForAnyRequest();
1.726 + }
1.727 +
1.728 + op1 = f1.End();
1.729 + op2 = f2.End();
1.730 +
1.731 + endTime.HomeTime();
1.732 + timeTaken=endTime.MicroSecondsFrom(startTime);
1.733 +
1.734 + dtime = timeTaken.Int64();
1.735 +
1.736 + TTest::Printf(_L("%c: %8d reads in %6d mS = %8d bytes per second\n"),
1.737 + (TUint)dc1, op1, I64LOW(dtime)/1000, GetSpeed(op1, dtime));
1.738 +
1.739 + if (dc1 != dc2)
1.740 + TTest::Printf(_L("%c: %8d reads in %6d mS = %8d bytes per second\n"),
1.741 + (TUint)dc2, op2, I64LOW(dtime)/1000, GetSpeed(op2, dtime));
1.742 +
1.743 + AddStats(gRdStats, MAKE_TINT64(0, op1 + op2) * MAKE_TINT64(0, KBufLen) * MAKE_TINT64(0, KSecond), dtime);
1.744 +
1.745 + test.Printf(_L("\n"));
1.746 + test.Printf(_L("average write throughput = %d bytes/sec\n"), GetSpeed(gWrStats));
1.747 + test.Printf(_L("average read throughput = %d bytes/sec\n"), GetSpeed(gRdStats));
1.748 + test.Printf(_L("\n"));
1.749 + gWrStats.Init();
1.750 + gRdStats.Init();
1.751 +
1.752 + timer.Cancel();
1.753 + timer.Close();
1.754 + f1.Close();
1.755 + f2.Close();
1.756 + // delay for a second to allow the close to complete before dismounting.
1.757 + User::After(1000000);
1.758 + return KErrNone;
1.759 + }
1.760 +
1.761 +#if defined(TEST_SYNC_IN_THREAD) || defined(TEST_ASYNC_IN_THREAD)
1.762 +
1.763 +LOCAL_C TInt CreateThread(TThreadFunction aFunc, TChar c, TOper aOper)
1.764 +/// Create a thread to do the appropriate operation on a drive.
1.765 + {
1.766 + TBuf<2> drive(_L("?"));
1.767 + TBuf<64> name;
1.768 + drive[0] = TText(c);
1.769 + drive.UpperCase();
1.770 + TThreadData& d = TTest::Data(gThreadNumber);
1.771 + d.iFile.Format(_L("%S:\\TEST%d.FILE"), &drive, gThreadNumber);
1.772 + d.iData = (aOper == EWrite ? &aOper : NULL);
1.773 + name.Format(_L("Test_%S_%d"), &drive, gThreadNumber);
1.774 + TInt r = TTest::Create(gThreadNumber, aFunc, name);
1.775 + ++gThreadNumber;
1.776 + return r;
1.777 + }
1.778 +
1.779 +LOCAL_C TInt RunThreads(TThreadFunction aFunc, TChar aDrive1, TChar aDrive2, TOper aOper)
1.780 +/// Run threads to test one drive against the other at the same time.
1.781 +/// The thread will report any error and return it as a value, the program will
1.782 +/// exit at a higher level after cleaning up.
1.783 + {
1.784 + TInt r;
1.785 + gThreadNumber = 0;
1.786 + if ((r = CreateThread(aFunc, aDrive1, aOper)) != KErrNone) return r;
1.787 + if ((r = CreateThread(aFunc, aDrive2, aOper)) != KErrNone) return r;
1.788 + TTest::Printf();
1.789 + r = TTest::Run();
1.790 + TTest::Printf();
1.791 + return r;
1.792 + }
1.793 +
1.794 +LOCAL_C TInt testThreads(TThreadFunction aFunc, TChar c, TChar d)
1.795 +/// Run threads testing read and write of the drives both ways round.
1.796 +/// The thread will report any error and return it as a value, the program will
1.797 +/// exit at a higher level after cleaning up.
1.798 + {
1.799 + TInt r;
1.800 + if ((r = RunThreads(aFunc, c, d, EWrite)) != KErrNone) return r;
1.801 + if ((r = RunThreads(aFunc, c, d, ERead)) != KErrNone) return r;
1.802 + if ((r = RunThreads(aFunc, d, c, EWrite)) != KErrNone) return r;
1.803 + if ((r = RunThreads(aFunc, d, c, ERead)) != KErrNone) return r;
1.804 + // display totals;
1.805 + test.Printf(_L("average write throughput = %d bytes/sec\n"), GetSpeed(gWrStats));
1.806 + test.Printf(_L("average read throughput = %d bytes/sec\n"), GetSpeed(gRdStats));
1.807 + test.Printf(_L("\n"));
1.808 + gWrStats.Init();
1.809 + gRdStats.Init();
1.810 + return r;
1.811 + }
1.812 +
1.813 +#endif
1.814 +
1.815 +LOCAL_C TInt parseCmd(TChar& aDrvCh1, TChar& aDrvCh2)
1.816 +/// Get parameters from the comand line; if there aren't enough then
1.817 +/// prompt the user for them and return KErrAbort if ^C is pressed.
1.818 + {
1.819 + while (aDrvCh1 < 'A' || aDrvCh1 > 'Z')
1.820 + {
1.821 + test.Printf(_L("Enter drive letter: "));
1.822 + while (aDrvCh1 < 'A' || aDrvCh1 > 'Z')
1.823 + {
1.824 + if (aDrvCh1 == 0x03)
1.825 + return KErrAbort;
1.826 + aDrvCh1 = User::UpperCase(test.Getch());
1.827 + }
1.828 + if (!DriveIsOK(aDrvCh1))
1.829 + {
1.830 + test.Printf(_L("%c: is not a valid drive\n"), (TUint)aDrvCh1);
1.831 + aDrvCh1 = 0;
1.832 + }
1.833 + else
1.834 + {
1.835 + TInt drv;
1.836 + TheFs.CharToDrive(aDrvCh1, drv);
1.837 + TheFs.FileSystemName(gFsName1, drv);
1.838 + test.Printf(_L("%c: (%S)\n"), (TUint)aDrvCh1, &gFsName1);
1.839 + }
1.840 + }
1.841 +
1.842 + while (aDrvCh2 < 'A' || aDrvCh2 > 'Z')
1.843 + {
1.844 + test.Printf(_L("Enter drive letter: "));
1.845 + while (aDrvCh2 < 'A' || aDrvCh2 > 'Z')
1.846 + {
1.847 + if (aDrvCh2 == 0x03)
1.848 + return KErrAbort;
1.849 + aDrvCh2 = User::UpperCase(test.Getch());
1.850 + }
1.851 + if (!DriveIsOK(aDrvCh2))
1.852 + {
1.853 + test.Printf(_L("%c: is not a valid drive\n"), (TUint)aDrvCh2);
1.854 + aDrvCh2 = 0;
1.855 + }
1.856 + else
1.857 + {
1.858 + TInt drv;
1.859 + TheFs.CharToDrive(aDrvCh2, drv);
1.860 + TheFs.FileSystemName(gFsName2, drv);
1.861 + test.Printf(_L("%c: (%S)\n"), (TUint)aDrvCh2, &gFsName2);
1.862 + }
1.863 + }
1.864 + return KErrNone;
1.865 + }
1.866 +
1.867 +GLDEF_C void CallTestsL()
1.868 +//
1.869 +// Do all tests
1.870 +//
1.871 + {
1.872 + TInt r = TTest::Init();
1.873 + test(r == KErrNone);
1.874 +
1.875 + TChar drvch0 = TTest::DefaultDriveChar();
1.876 + TChar drvch1 = 0;
1.877 + TChar drvch2 = 0;
1.878 + TInt drive0;
1.879 + TInt drive1;
1.880 + TInt drive2;
1.881 +
1.882 + const TInt KMaxArgs = 4;
1.883 + TPtrC argv[KMaxArgs];
1.884 + TInt argc = TTest::ParseCommandArguments(argv, KMaxArgs);
1.885 + if (argc > 1)
1.886 + drvch0 = User::UpperCase(argv[1][0]);
1.887 + if (argc > 2)
1.888 + drvch1 = User::UpperCase(argv[2][0]);
1.889 + if (argc > 3)
1.890 + drvch2 = User::UpperCase(argv[3][0]);
1.891 +
1.892 + r = TheFs.CharToDrive(drvch0, drive0);
1.893 + test(r == KErrNone);
1.894 +
1.895 + if (TheFs.IsValidDrive(drive0))
1.896 + MountTestFileSystem(drive0);
1.897 + else
1.898 + test.Printf(_L("Unable to mount test file system\n"));
1.899 +
1.900 + r = parseCmd(drvch1, drvch2);
1.901 + if (r != KErrNone)
1.902 + {
1.903 + UnmountFileSystem(drive0);
1.904 + User::Panic(_L("USER ABORT"), 0);
1.905 + }
1.906 +
1.907 + r = TheFs.CharToDrive(drvch1, drive1);
1.908 + test(r == KErrNone);
1.909 + r = TheFs.CharToDrive(drvch2, drive2);
1.910 + test(r == KErrNone);
1.911 +
1.912 + r = TheFs.FileSystemName(gFsName1, drive1);
1.913 + test(r == KErrNone || r == KErrNotFound);
1.914 + r = TheFs.FileSystemName(gFsName2, drive2);
1.915 + test(r == KErrNone || r == KErrNotFound);
1.916 +
1.917 + gDataLock.CreateLocal();
1.918 +
1.919 + if (drive1 == drive2)
1.920 + {
1.921 +// !!! Disable platform security tests until we get the new APIs
1.922 +// if (User::Capability() & KCapabilityRoot)
1.923 +// CheckMountLFFS(TheFs, drvch1);
1.924 +
1.925 + test.Printf(_L("Using drive %c: (%S)\n"),
1.926 + (TUint)drvch1, &gFsName1);
1.927 + if (r == KErrNone)
1.928 + {
1.929 + test.Next(_L("Test with drive asynchronous"));
1.930 + RemountFileSystem(drive1, EFalse);
1.931 + testAsyncAccess(drvch1, drvch1);
1.932 + }
1.933 +
1.934 + if (r == KErrNone)
1.935 + {
1.936 + test.Next(_L("Test with drive synchronous"));
1.937 + RemountFileSystem(drive1, ETrue);
1.938 + testAsyncAccess(drvch1, drvch1);
1.939 + }
1.940 + }
1.941 + else
1.942 + {
1.943 +// !!! Disable platform security tests until we get the new APIs
1.944 +/* if (User::Capability() & KCapabilityRoot)
1.945 + {
1.946 + CheckMountLFFS(TheFs, drvch1);
1.947 + CheckMountLFFS(TheFs, drvch2);
1.948 + }
1.949 +*/
1.950 + test.Printf(_L("Using drives %c: (%S) and %c: (%S)\n"),
1.951 + (TUint)drvch1, &gFsName1, (TUint)drvch2, &gFsName2);
1.952 +
1.953 +#if !defined(TEST_ASYNC_IN_THREAD)
1.954 +
1.955 + if (r == KErrNone)
1.956 + {
1.957 + test.Next(_L("Test async r/w with both drives async"));
1.958 + RemountFileSystem(drive1, EFalse);
1.959 + RemountFileSystem(drive2, EFalse);
1.960 + testAsyncAccess(drvch1, drvch2);
1.961 + }
1.962 +
1.963 + if (r == KErrNone)
1.964 + {
1.965 + test.Next(_L("Test async r/w with 1st drive sync and 2nd async"));
1.966 + RemountFileSystem(drive1, ETrue);
1.967 + RemountFileSystem(drive2, EFalse);
1.968 + testAsyncAccess(drvch1, drvch2);
1.969 + }
1.970 +
1.971 + if (r == KErrNone)
1.972 + {
1.973 + test.Next(_L("Test async r/w with 1st drive async and 2nd sync"));
1.974 + RemountFileSystem(drive1, EFalse);
1.975 + RemountFileSystem(drive2, ETrue);
1.976 + testAsyncAccess(drvch1, drvch2);
1.977 + }
1.978 +
1.979 + if (r == KErrNone)
1.980 + {
1.981 + test.Next(_L("Test async r/w with both drives sync"));
1.982 + RemountFileSystem(drive1, ETrue);
1.983 + RemountFileSystem(drive2, ETrue);
1.984 + testAsyncAccess(drvch1, drvch2);
1.985 + }
1.986 +
1.987 +#else
1.988 +
1.989 + if (r == KErrNone)
1.990 + {
1.991 + test.Next(_L("Test async r/w with both drives asynchronous"));
1.992 + RemountFileSystem(drive1, EFalse);
1.993 + RemountFileSystem(drive2, EFalse);
1.994 + r = testThreads(testAsyncAccess, drvch1, drvch2);
1.995 + }
1.996 +
1.997 + if (r == KErrNone)
1.998 + {
1.999 + test.Next(_L("Test async r/w with one drive sync and one async"));
1.1000 + RemountFileSystem(drive1, ETrue);
1.1001 + RemountFileSystem(drive2, EFalse);
1.1002 + r = testThreads(testAsyncAccess, drvch1, drvch2);
1.1003 + }
1.1004 +
1.1005 + if (r == KErrNone)
1.1006 + {
1.1007 + test.Next(_L("Test async r/w with both drives synchronous"));
1.1008 + RemountFileSystem(drive1, ETrue);
1.1009 + RemountFileSystem(drive2, ETrue);
1.1010 + r = testThreads(testAsyncAccess, drvch1, drvch2);
1.1011 + }
1.1012 +#endif
1.1013 +
1.1014 +#if defined(TEST_SYNC_IN_THREAD)
1.1015 +
1.1016 + if (r == KErrNone)
1.1017 + {
1.1018 + test.Next(_L("Test sync r/w with both drives asynchronous"));
1.1019 + RemountFileSystem(drive1, EFalse);
1.1020 + RemountFileSystem(drive2, EFalse);
1.1021 + r = testThreads(testSyncAccess, drvch1, drvch2);
1.1022 + }
1.1023 +
1.1024 + if (r == KErrNone)
1.1025 + {
1.1026 + test.Next(_L("Test sync r/w with one drive sync and one async"));
1.1027 + RemountFileSystem(drive1, ETrue);
1.1028 + RemountFileSystem(drive2, EFalse);
1.1029 + r = testThreads(testSyncAccess, drvch1, drvch2);
1.1030 + }
1.1031 +
1.1032 + if (r == KErrNone)
1.1033 + {
1.1034 + test.Next(_L("Test sync r/w with both drives synchronous"));
1.1035 + RemountFileSystem(drive1, ETrue);
1.1036 + RemountFileSystem(drive2, ETrue);
1.1037 + r = testThreads(testSyncAccess, drvch1, drvch2);
1.1038 + }
1.1039 +#endif
1.1040 + }
1.1041 +
1.1042 + gDataLock.Close();
1.1043 +
1.1044 + UnmountFileSystem(drive0);
1.1045 + test(r == 0);
1.1046 + }
1.1047 +
1.1048 +
1.1049 +GLDEF_C TInt E32Main()
1.1050 +//
1.1051 +// Main entry point
1.1052 +//
1.1053 + {
1.1054 + TInt r;
1.1055 +
1.1056 + CTrapCleanup* cleanup;
1.1057 + cleanup=CTrapCleanup::New();
1.1058 + __UHEAP_MARK;
1.1059 +
1.1060 + test.Title();
1.1061 + test.Start(_L("Starting tests..."));
1.1062 +
1.1063 + r=TheFs.Connect();
1.1064 + test(r==KErrNone);
1.1065 +
1.1066 + // TheFs.SetAllocFailure(gAllocFailOn);
1.1067 + TTime timerC;
1.1068 + timerC.HomeTime();
1.1069 +
1.1070 + // Do the tests
1.1071 + TRAP(r,CallTestsL());
1.1072 +
1.1073 + // reset the debug register
1.1074 + TheFs.SetDebugRegister(0);
1.1075 +
1.1076 + TTime endTimeC;
1.1077 + endTimeC.HomeTime();
1.1078 + TTimeIntervalSeconds timeTakenC;
1.1079 + r=endTimeC.SecondsFrom(timerC,timeTakenC);
1.1080 + test(r==KErrNone);
1.1081 + test.Printf(_L("Time taken for test = %d seconds\n"),timeTakenC.Int());
1.1082 + // TheFs.SetAllocFailure(gAllocFailOff);
1.1083 + TheFs.Close();
1.1084 + test.End();
1.1085 + test.Close();
1.1086 + __UHEAP_MARKEND;
1.1087 + delete cleanup;
1.1088 + return(KErrNone);
1.1089 + }