kerneltest/f32test/bench/t_notify_perf_impl.cpp
changeset 9 96e5fb8b040d
child 8 538db54a451d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32test\bench\t_notify_perf_impl.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "t_notify_perf.h"
       
    19 #include "t_server.h"
       
    20 
       
    21 extern void FileNameGen(TFileName& aName, TInt aNum, TBool aIsFile = ETrue);
       
    22 extern TInt FileOperationThread(TAny* aSetting);
       
    23 extern TInt NotificationOperationThread(TAny* aSetting);
       
    24 extern TInt KillerThread(TAny*);
       
    25 extern TUint OpNotifyMapping(TUint16& aOption, TInt aOperation);
       
    26 extern TBool CompareEntryName(const TEntry& aEntry1, const TEntry& aEntry2);
       
    27 extern void SafeTestL(TBool aResult, TInt aId, TInt aLine, TText* aFile);
       
    28 extern void SafeTestL(TInt aResult, TInt aExpected, TInt aId, TInt aLine, TText* aFile);
       
    29 
       
    30 const TInt KNotificationHeaderSize = (sizeof(TUint16)*2)+(sizeof(TUint));
       
    31 const TInt KMinNotificationBufferSize = 2*KNotificationHeaderSize + 2*KMaxFileName;
       
    32 
       
    33 TBool gPerfMeasure;
       
    34 TFileName gTestPath;
       
    35 TFileName gLogFilePath;
       
    36 RArray<RThread> gNotiThreads;
       
    37 RThread gFileThread;
       
    38 TBuf<50> gLogPostFix;
       
    39 
       
    40 // Prints out the filename
       
    41 #define ExpandMe(X)  L ## X
       
    42 #define Expand(X)    ExpandMe(X)
       
    43 
       
    44 // Safe test, so that sub-threads are not hanging after check fail
       
    45 #define SAFETEST0(a) SafeTestL(a,KNoThreadId,__LINE__,(TText*)Expand("t_notify_perf_impl.cpp"))
       
    46 #define SAFETEST1(a,b) SafeTestL(a,b,__LINE__,(TText*)Expand("t_notify_perf_impl.cpp"))
       
    47 #define SAFETEST2(a,b,c) SafeTestL(a,b,c,__LINE__,(TText*)Expand("t_notify_perf_impl.cpp"))
       
    48 
       
    49 
       
    50 TTestSetting::TTestSetting()
       
    51 : iNumFiles(0), iNumCli(0), iOption(0), iOperationList(NULL)
       
    52 	{
       
    53 	}
       
    54 
       
    55 TTestSetting::TTestSetting(TInt aNumFiles, TInt aNumCli, TUint16 aOpt, const TUint* aOpList)
       
    56 : iNumFiles(aNumFiles), iNumCli(aNumCli), iOption(aOpt), iOperationList(aOpList)
       
    57 	{
       
    58 	}
       
    59 
       
    60 //===========================================================
       
    61 
       
    62 CTimerLogger* CTimerLogger::NewL(const TFileName& aLogFile)
       
    63 	{
       
    64 	CTimerLogger* self = new(ELeave) CTimerLogger();
       
    65 	CleanupStack::PushL(self);
       
    66 	self->ConstructL(aLogFile);
       
    67 	CleanupStack::Pop(self);
       
    68 	return self;
       
    69 	}
       
    70 
       
    71 void CTimerLogger::ConstructL(const TFileName& aLogFile)
       
    72 	{
       
    73 	User::LeaveIfError(HAL::Get(HALData::ENanoTickPeriod, iTickPeriod));
       
    74 	iLogFile.Copy(aLogFile);
       
    75 	}
       
    76 
       
    77 CTimerLogger::CTimerLogger()
       
    78 :  iTiming(EFalse), iTickNumber(0), iTimeScale(KDefaultTimeScale)
       
    79 	{
       
    80 	iFs.Connect();
       
    81 	}
       
    82 
       
    83 CTimerLogger::~CTimerLogger()
       
    84 	{
       
    85 	iFs.Close();
       
    86 	}
       
    87 
       
    88 // Write Logs
       
    89 TInt CTimerLogger::Log(const TDesC& aDes, TBool aIsLine)
       
    90 	{
       
    91 	RFile file;
       
    92 	iFs.Connect();
       
    93 	
       
    94 	TInt err = file.Open(iFs,iLogFile,EFileShareExclusive|EFileWrite);
       
    95 	SAFETEST0(err == KErrNone || err == KErrNotFound || err == KErrPathNotFound);
       
    96 	
       
    97 	if (err != KErrNone)
       
    98 		{
       
    99 		err = iFs.MkDirAll(iLogFile);
       
   100 		SAFETEST0(err == KErrNone || err == KErrAlreadyExists);
       
   101 		err = file.Create(iFs,iLogFile,EFileShareExclusive|EFileWrite);
       
   102 		SAFETEST0(err == KErrNone);
       
   103 		}
       
   104 	
       
   105 	TBuf8<240> data;
       
   106 	data.Copy(aDes);
       
   107 	if (aIsLine)
       
   108 		{
       
   109 		data.Append(_L8("\r\n"));
       
   110 		}
       
   111 		
       
   112 	TInt offset = 0;
       
   113 	err = file.Seek(ESeekEnd, offset);
       
   114 	SAFETEST0(err == KErrNone);
       
   115 	err = file.Write(data);
       
   116 	SAFETEST0(err == KErrNone);
       
   117 
       
   118 	file.Close();
       
   119 	iFs.Close();
       
   120 	return err;
       
   121 	}
       
   122 
       
   123 // Write Logs and also print the line written in the console
       
   124 TInt CTimerLogger::LogAndPrint(const TDesC& aDes, TBool aIsLine)
       
   125 	{
       
   126 	TInt err = KErrNone;
       
   127 	RDebug::Print(aDes);
       
   128 	if (gPerfMeasure)
       
   129 	    err = Log(aDes, aIsLine);
       
   130 	return err;
       
   131 	}
       
   132 
       
   133 // Write and print the time result
       
   134 TInt CTimerLogger::LogTestStepTime(TUint aOp, TInt aNum)
       
   135 	{
       
   136 	if (iTiming)
       
   137 		return KErrGeneral;
       
   138 	
       
   139 	TBuf<100> buf;
       
   140 	switch (aOp)
       
   141 		{
       
   142 		case EOpCreate:
       
   143 			buf.Append(_L("Create - "));
       
   144 			break;
       
   145 		case EOpReplace:
       
   146 			buf.Append(_L("Replace - "));
       
   147 			break;
       
   148 		case EOpChgAttr:
       
   149 			buf.Append(_L("Change Attribute - "));
       
   150 			break;
       
   151 		case EOpRename:
       
   152 			buf.Append(_L("Rename - "));
       
   153 			break;
       
   154 		case EOpWrite:
       
   155 			buf.Append(_L("Write - "));
       
   156 			break;
       
   157 		case EOpResize:
       
   158 			buf.Append(_L("Resize - "));
       
   159 			break;
       
   160 		case EOpDelete:
       
   161 			buf.Append(_L("Delete - "));
       
   162 			break;
       
   163 		case EOpManyChanges:
       
   164 			buf.AppendFormat(_L("%d Changes on Single File - "), aNum);
       
   165 			break;
       
   166 		case EOpManyFiles:
       
   167 			buf.AppendFormat(_L("Small Changes on %d Files - "), aNum);
       
   168 			break;
       
   169 		case EOpCreateDir:
       
   170 			buf.Append(_L("Create(dir) - "));
       
   171 			break;
       
   172 		case EOpRenameDir:
       
   173 			buf.Append(_L("Rename(dir) - "));
       
   174 			break;
       
   175 		case EOpDeleteDir:
       
   176 			buf.Append(_L("Delete(dir) - "));
       
   177 			break;
       
   178 		case EOpMixed:
       
   179 			buf.AppendFormat(_L("%d Mixed Operations - "), aNum*18);
       
   180 		default:
       
   181 			break;
       
   182 		}
       
   183 	
       
   184 	TReal time = (static_cast<TReal>(iTickNumber) * iTickPeriod) / iTimeScale;
       
   185 	buf.AppendFormat(_L("time: %d ms"), static_cast<TInt>(time));
       
   186 	return LogAndPrint(buf);
       
   187 	}
       
   188 
       
   189 // write and print the test case discription
       
   190 TInt CTimerLogger::LogSettingDescription(const TInt aNumFile, const TInt aNumCli, const TUint16 aOption, TBool aNumOpVaries)
       
   191 	{	
       
   192 	LogAndPrint(_L("===================================================="));
       
   193 	
       
   194 	TBuf<120> buf;
       
   195 	buf.Append(_L("Test: "));
       
   196 	if (!aNumOpVaries)
       
   197 		{
       
   198 		buf.AppendFormat(_L("%d files/directories, %d Clients, "), aNumFile, aNumCli);
       
   199 		}
       
   200 	
       
   201 	// Notification Type
       
   202 	switch(aOption & KNotifyOptionMask)
       
   203 		{		
       
   204 		case ENoNotify:
       
   205 			buf.Append(_L("No Notification"));
       
   206 			break;
       
   207 		case EEnhanced:
       
   208 			buf.Append(_L("Enhanced"));
       
   209 			break;
       
   210 		case EOriginal:
       
   211 			buf.Append(_L("Original"));
       
   212 			break;
       
   213 		case EPlugin:
       
   214 			buf.Append(_L("Nokia Plug-in"));
       
   215 			break;
       
   216 		default:
       
   217 			return KErrArgument;
       
   218 		}
       
   219 	
       
   220 	if (aOption & EBigFilter)
       
   221 		{
       
   222 		buf.Append(_L(", 100 Filters"));
       
   223 		}
       
   224 	
       
   225 	if (aOption & EReportChg)
       
   226 		{
       
   227 		buf.Append(_L(", Change Reporting"));
       
   228 		}
       
   229 	else
       
   230 		{
       
   231 		buf.Append(_L(", Not Report Changes"));
       
   232 		}
       
   233 	
       
   234 	if (aOption & EEnhanced)
       
   235 		{
       
   236 		if (aOption & EBigBuffer)
       
   237 			{
       
   238 			buf.Append(_L(", Big Buffer"));
       
   239 			} 
       
   240 		else
       
   241 			{
       
   242 			buf.Append(_L(", Small Buffer"));
       
   243 			}
       
   244 		
       
   245 		if (aOption & EMultiNoti1)
       
   246 			{
       
   247 			buf.Append(_L(", Multi Notification Mode 1"));
       
   248 			}
       
   249 		else if (aOption & EMultiNoti2)
       
   250 			{
       
   251 			buf.Append(_L(", Multi Notification Mode 2"));
       
   252 			}
       
   253 		}
       
   254 
       
   255 	LogAndPrint(buf);
       
   256 	LogAndPrint(_L("----------------------------------------------------"));
       
   257 	
       
   258 	return KErrNone;
       
   259 	}
       
   260 
       
   261 //===========================================================
       
   262 
       
   263 CTestExecutor::CTestExecutor(TTestSetting& aSetting)
       
   264 : iTestSetting(aSetting)
       
   265 	{
       
   266 	}
       
   267 
       
   268 CTestExecutor::~CTestExecutor()
       
   269 	{
       
   270 	}
       
   271 
       
   272 void CTestExecutor::KillAllTestThreads()
       
   273     {
       
   274     RThread killer;
       
   275     killer.Create(_L("KillerThread"), KillerThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, NULL); 
       
   276     killer.Resume();
       
   277    
       
   278     TRequestStatus status;
       
   279     killer.Logon(status);
       
   280     User::WaitForRequest(status);
       
   281     TInt err = killer.ExitReason();
       
   282     test(err == KErrNone);
       
   283     }
       
   284 
       
   285 // start run a test case
       
   286 void CTestExecutor::RunTestCaseL()
       
   287 	{
       
   288 	RSemaphore smphF;
       
   289 	smphF.CreateLocal(0);
       
   290 	RSemaphore smphN;
       
   291 	smphN.CreateLocal(0);
       
   292 		
       
   293 	RArray<RThread> notiThreads; // list of handles of notification threads
       
   294 	RPointerArray<CTimerLogger> loggerList;
       
   295 	
       
   296 	TUint16 count = 0;
       
   297 	TUint16 option = iTestSetting.iOption;
       
   298 	while (count < iTestSetting.iNumCli)
       
   299 		{
       
   300 		test(count < 16);
       
   301 		iTestSetting.iOption = (TUint16)(option + count); // Put Thread ID in option
       
   302 		
       
   303 		TThreadParam param;
       
   304 		param.iSetting = iTestSetting;
       
   305 		param.iSmphFT = &smphF;
       
   306 		param.iSmphNT = &smphN;
       
   307 			
       
   308 		TFileName logName;
       
   309 		logName.FillZ();
       
   310 		
       
   311 		if (gPerfMeasure)
       
   312 		    {
       
   313             logName.Append(gLogFilePath);
       
   314             if (iTestSetting.iNumCli == 1)
       
   315                 logName.Append(_L("SingleClient"));
       
   316             else
       
   317                 logName.AppendFormat(_L("MultiClient%02d"), count);
       
   318             
       
   319             logName.Append(gLogPostFix);
       
   320 		    }
       
   321 		
       
   322 		CTimerLogger* logger = CTimerLogger::NewL(logName);
       
   323 		CleanupStack::PushL(logger);
       
   324 		
       
   325 		param.iLogger = logger;
       
   326 		param.iLoggerArray = NULL;
       
   327 		
       
   328 		TUint operation = *iTestSetting.iOperationList;
       
   329 		TBool numFilesVaries = EFalse; 
       
   330 		
       
   331 		if (operation == EOpManyFiles || operation == EOpManyChanges || operation == EOpMixed)
       
   332 			{
       
   333 			numFilesVaries = ETrue;
       
   334 			}
       
   335 		logger->LogSettingDescription(iTestSetting.iNumFiles, iTestSetting.iNumCli, iTestSetting.iOption, numFilesVaries);
       
   336 		
       
   337 		loggerList.AppendL(logger);
       
   338 		
       
   339 		TBuf<20> threadName;
       
   340 		threadName.AppendFormat(_L("NotificationThread%02d"), count);
       
   341 
       
   342 		RThread notifyOp;
       
   343 		notifyOp.Create(threadName, NotificationOperationThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, &param);
       
   344 		
       
   345 		notiThreads.AppendL(notifyOp);
       
   346 		
       
   347 		notifyOp.Resume();
       
   348 		
       
   349 		smphF.Wait();	// Wait for the parameters being properly passed
       
   350 		
       
   351 		CleanupStack::Pop(logger);
       
   352 		count++;
       
   353 		}
       
   354 	
       
   355 	gNotiThreads = notiThreads;
       
   356 	
       
   357 	if (iTestSetting.iNumCli == 0)	// no notification
       
   358 		{
       
   359 		TFileName logName;
       
   360 		logName.Append(gLogFilePath);
       
   361 		logName.Append(_L("SingleClient"));
       
   362 		logName.Append(gLogPostFix);
       
   363 	
       
   364 		CTimerLogger* logger = CTimerLogger::NewL(logName);
       
   365 		CleanupStack::PushL(logger);
       
   366 		
       
   367 		logger->LogSettingDescription(iTestSetting.iNumFiles, iTestSetting.iNumCli, iTestSetting.iOption);
       
   368 		
       
   369 		loggerList.AppendL(logger);
       
   370 		CleanupStack::Pop(logger);
       
   371 		}
       
   372 	
       
   373 	TThreadParam paramFileOp;
       
   374 	paramFileOp.iSetting = iTestSetting;
       
   375 	paramFileOp.iSmphFT = &smphF;
       
   376 	paramFileOp.iSmphNT = &smphN;
       
   377 	paramFileOp.iLogger = NULL;
       
   378 	paramFileOp.iLoggerArray = &loggerList;
       
   379 	
       
   380 	RThread fileOp;
       
   381 	fileOp.Create(_L("FileOperationThread"), FileOperationThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, &paramFileOp);	
       
   382 	gFileThread = fileOp;
       
   383 	
       
   384 	fileOp.Resume();
       
   385 	
       
   386 	TInt err;
       
   387 	
       
   388 	TRequestStatus status;
       
   389 	fileOp.Logon(status);
       
   390 	User::WaitForRequest(status);
       
   391 	err = fileOp.ExitReason();
       
   392 	test(err == KErrNone);
       
   393 		
       
   394 	count = 0;
       
   395 	while(count < notiThreads.Count())
       
   396 		{
       
   397 		notiThreads[count].Logon(status);
       
   398 		User::WaitForRequest(status);
       
   399 		err = notiThreads[count].ExitReason();
       
   400 		test(err == KErrNone);
       
   401 		count++;
       
   402 		}
       
   403 	
       
   404 	CLOSE_AND_WAIT(fileOp);
       
   405 	
       
   406 	count = 0;
       
   407 	while(count < notiThreads.Count())
       
   408 		{
       
   409 		RThread thread = notiThreads[count];
       
   410 		CLOSE_AND_WAIT(thread);
       
   411 		count++;
       
   412 		}
       
   413 	
       
   414 	for (TInt i = 0; i < loggerList.Count(); i++)
       
   415 		{
       
   416 		loggerList[i]->LogAndPrint(_L("===================================================="));
       
   417 		}
       
   418 	
       
   419 	smphN.Close();
       
   420 	smphF.Close();
       
   421 	loggerList.ResetAndDestroy();
       
   422 	loggerList.Close();
       
   423 	notiThreads.Reset();
       
   424 	notiThreads.Close();
       
   425 	}
       
   426 
       
   427 //===========================================================
       
   428 
       
   429 CFileOperator::CFileOperator(const TTestSetting& aSetting, RPointerArray<CTimerLogger>& aLoggerArray, RSemaphore* aSmphFT, RSemaphore* aSmphNT)
       
   430 : iFirstFile(0)
       
   431 	{
       
   432 	iNumFiles = aSetting.iNumFiles;
       
   433 	iOption = aSetting.iOption;
       
   434 	iCurrentOp = aSetting.iOperationList;
       
   435 	iNumCli = aSetting.iNumCli;
       
   436 	
       
   437 	iLoggers = aLoggerArray; 
       
   438 	iSmphS = aSmphNT;
       
   439 	iSmphW = aSmphFT;
       
   440 
       
   441 	iFs.Connect();
       
   442 	}
       
   443 
       
   444 CFileOperator::~CFileOperator()
       
   445 	{
       
   446 	iFs.Close();
       
   447 	}
       
   448 
       
   449 // starts measuring for all the notification thread
       
   450 // the loggers in iLogger are shared by Notification thread
       
   451 void CFileOperator::MesureStartsAll()
       
   452 	{
       
   453 	TInt i = 0;
       
   454 	while (i < iNumCli)
       
   455 		{
       
   456 		iLoggers[i]->MeasureStart();
       
   457 		i++;
       
   458 		}
       
   459 	}
       
   460 
       
   461 // Wait for all notification threads to signal
       
   462 void CFileOperator::WaitForSignalsAll()
       
   463 	{
       
   464 	TInt i = 0;
       
   465 	while (i < iNumCli)
       
   466 		{
       
   467 		iSmphW->Wait();
       
   468 		i++;
       
   469 		}
       
   470 	}
       
   471 
       
   472 // prepare each test step
       
   473 void CFileOperator::TestStepPrepare(TUint aOp)
       
   474 	{
       
   475 	RDebug::Print(_L("Preparing for the next test step..."));
       
   476 	switch (aOp)
       
   477 		{
       
   478 		case EOpReplace:
       
   479 			{
       
   480 			User::After(1500000); // Wait for 1.5 sec so that the new files have different modified time
       
   481 			RFile file;
       
   482 			TInt count = iFirstFile + iNumFiles;
       
   483 			while (count < (iFirstFile + (iNumFiles * 2)))
       
   484 				{
       
   485 				TFileName nextFile;
       
   486 				FileNameGen(nextFile, count);
       
   487 				file.Create(iFs, nextFile, EFileRead);
       
   488 				file.Close();
       
   489 				count++;
       
   490 				}
       
   491 			break;
       
   492 			}
       
   493 		case EOpManyChanges:
       
   494 			{
       
   495 			RFile file;
       
   496 			TFileName nextFile;
       
   497 			FileNameGen(nextFile, 9999);
       
   498 			file.Create(iFs, nextFile, EFileRead);
       
   499 			file.Close();
       
   500 			break;
       
   501 			}
       
   502 		case EOpManyFiles:
       
   503 			{
       
   504 			CDir* list;
       
   505 			iFs.GetDir(gTestPath, KEntryAttMaskSupported, ESortNone, list);
       
   506 			TInt count = list->Count();
       
   507 			delete list;
       
   508 			
       
   509 			RFile file;
       
   510 			
       
   511 			for (TInt i = 0; i < iNumFiles - count; i++)
       
   512 				{
       
   513 				TFileName nextFile;
       
   514 				FileNameGen(nextFile, count + i);
       
   515 				file.Create(iFs, nextFile, EFileRead);
       
   516 				file.Close();
       
   517 				}
       
   518 			
       
   519 			break;
       
   520 			}
       
   521 		// No preparation for other operations
       
   522 		default:
       
   523 			break;
       
   524 		}
       
   525 	RDebug::Print(_L("Preparation done..."));
       
   526 	}
       
   527 
       
   528 // Finish each test step, do some clearing or test setting modification
       
   529 void CFileOperator::TestStepFinish(TUint aOp)
       
   530 	{
       
   531 	RDebug::Print(_L("Finishing the test step..."));
       
   532 	switch (aOp)
       
   533 		{
       
   534 		case EOpRenameDir:
       
   535 		case EOpRename:
       
   536 			{
       
   537 			iFirstFile += iNumFiles;
       
   538 			break;
       
   539 			}
       
   540 		case EOpDelete:
       
   541 		case EOpDeleteDir:
       
   542 			{
       
   543 			iFirstFile = 0;
       
   544 			break;
       
   545 			}
       
   546 		case EOpManyChanges:
       
   547 			{
       
   548 			TFileName fileName;
       
   549 			FileNameGen(fileName, 9999);
       
   550 			iFs.Delete(fileName);
       
   551 			iNumFiles += 1000;
       
   552 			break;
       
   553 			}
       
   554 		case EOpManyFiles:
       
   555 			{
       
   556 			iNumFiles += 1000;
       
   557 			break;
       
   558 			}
       
   559 	    case EOpMixed:
       
   560 	        {
       
   561 	        iNumFiles += 50;
       
   562 	        }
       
   563 	    // no clearing for other operations
       
   564 		default:
       
   565 			break;
       
   566 		}
       
   567 	RDebug::Print(_L("***** Test step finished *****"));
       
   568 	RDebug::Print(_L("\n"));
       
   569 	}
       
   570 
       
   571 // perform the file operations
       
   572 void CFileOperator::DoChangesL()
       
   573 	{
       
   574 	while(*iCurrentOp != EOpEnd)
       
   575 		{
       
   576 		TestStepPrepare(*iCurrentOp);
       
   577 		
       
   578 		if (iOption & ENoNotify)
       
   579 			{
       
   580 			iLoggers[0]->MeasureStart();
       
   581 			}
       
   582 		else
       
   583 			{
       
   584 			iSmphS->Signal(iNumCli);	// Signal notification threads that preparation is done
       
   585 			WaitForSignalsAll();	// Wait for notification threads to finish requesting notifications 
       
   586 			MesureStartsAll();
       
   587 			}
       
   588 		
       
   589 		RDebug::Print(_L("Start Timing and File operations..."));	
       
   590 		switch(*iCurrentOp)
       
   591 			{
       
   592 			case EOpCreate:
       
   593 				DoCreateL(); 
       
   594 				break;
       
   595 			case EOpReplace:
       
   596 				DoReplaceL();
       
   597 				break;
       
   598 			case EOpChgAttr:
       
   599 				DoChangeAttL();
       
   600 				break;
       
   601 			case EOpRename:
       
   602 				DoRenameL();
       
   603 				break;
       
   604 			case EOpWrite:
       
   605 				DoWriteL(); 
       
   606 				break;
       
   607 			case EOpResize:
       
   608 				DoResizeL(); 
       
   609 				break;
       
   610 			case EOpDelete:
       
   611 				DoDeleteL();
       
   612 				break;
       
   613 			case EOpManyChanges:
       
   614 				DoManyChangesOnSingleFileL();
       
   615 				break;
       
   616 			case EOpManyFiles:
       
   617 				DoSmallChangesOnManyFilesL();
       
   618 				break;
       
   619 			case EOpCreateDir:
       
   620 				DoCreateDirL();
       
   621 				break;
       
   622 			case EOpRenameDir:
       
   623 				DoRenameDirL();
       
   624 				break;
       
   625 			case EOpDeleteDir:
       
   626 				DoDeleteDirL();
       
   627 				break;
       
   628 			case EOpMixed:
       
   629 				DoMixedOperationsL();
       
   630 				break;
       
   631 			default: 
       
   632 				User::Leave(KErrArgument);
       
   633 			}
       
   634 		RDebug::Print(_L("File Operation Ended..."));
       
   635 		
       
   636 		if (iOption & ENoNotify)
       
   637 			{
       
   638 			RDebug::Print(_L("Timing ended..."));
       
   639 			iLoggers[0]->MeasureEnd();
       
   640 			iLoggers[0]->LogTestStepTime(*iCurrentOp, iNumFiles);
       
   641 			}
       
   642 		else 
       
   643 			{
       
   644 			RFile file;
       
   645 			TFileName endFile(gLogFilePath);
       
   646 			endFile.Append(_L("test.end"));
       
   647 			TInt r = file.Replace(iFs, endFile, EFileWrite);
       
   648 			SAFETEST0(r == KErrNone);
       
   649 			file.Close();
       
   650 	
       
   651 			WaitForSignalsAll();	// Wait for notification threads to receive all the notifications 
       
   652 			}
       
   653 		
       
   654 		TestStepFinish(*iCurrentOp);
       
   655 			
       
   656 		iCurrentOp++;
       
   657 		}
       
   658 	}
       
   659 
       
   660 void CFileOperator::DoCreateL()
       
   661 	{
       
   662 	RFile file;
       
   663 	TInt count = iFirstFile;
       
   664 	
       
   665 	while (count < iFirstFile + iNumFiles)
       
   666 		{
       
   667 		TFileName nextFile;
       
   668 		FileNameGen(nextFile, count);
       
   669 
       
   670 		TInt r = file.Create(iFs, nextFile, EFileRead);
       
   671 		SAFETEST0(r == KErrNone);
       
   672 		file.Close();	
       
   673 		count++;
       
   674 		}
       
   675 	}
       
   676 
       
   677 void CFileOperator::DoReplaceL()
       
   678 	{
       
   679 	TInt count = iFirstFile;
       
   680 	
       
   681 	while (count < iFirstFile + iNumFiles)
       
   682 		{
       
   683 		TFileName newFile;
       
   684 		TFileName oldFile;
       
   685 		FileNameGen(newFile, count);
       
   686 		FileNameGen(oldFile, count + iNumFiles);
       
   687 		
       
   688 		iFs.Replace(oldFile, newFile);
       
   689 		count++;
       
   690 		}
       
   691 	}
       
   692 
       
   693 void CFileOperator::DoChangeAttL()
       
   694 	{
       
   695 	TInt count = iFirstFile;
       
   696 	
       
   697 	while (count < iFirstFile + iNumFiles)
       
   698 		{
       
   699 		TFileName nextFile;
       
   700 		FileNameGen(nextFile, count);
       
   701 		iFs.SetAtt(nextFile, KEntryAttNormal, KEntryAttArchive);
       
   702 		count++;
       
   703 		}
       
   704 	}
       
   705 
       
   706 void CFileOperator::DoRenameL()
       
   707 	{
       
   708 	TInt count = iFirstFile;
       
   709 	
       
   710 	while (count < iFirstFile + iNumFiles)
       
   711 		{
       
   712 		TFileName newFile;
       
   713 		TFileName oldFile;
       
   714 		FileNameGen(oldFile, count);
       
   715 		FileNameGen(newFile, count + iNumFiles);
       
   716 		
       
   717 		iFs.Rename(oldFile, newFile);
       
   718 		count++;
       
   719 		}
       
   720 	}
       
   721 
       
   722 void CFileOperator::DoWriteL()
       
   723 	{
       
   724 	RFile file;
       
   725 	TInt count = iFirstFile;
       
   726 	_LIT8(KData, "Some text for writing test of enhanced notification performance test.");
       
   727 	
       
   728 	while (count < iFirstFile + iNumFiles)
       
   729 		{
       
   730 		TFileName nextFile;
       
   731 		FileNameGen(nextFile, count);
       
   732 		file.Open(iFs, nextFile, EFileWrite);
       
   733 		file.Write(KData);
       
   734 		// Flush file to ensure notification is received
       
   735 		file.Flush();
       
   736 		file.Close();	
       
   737 		count++;
       
   738 		}
       
   739 	}
       
   740 
       
   741 void CFileOperator::DoResizeL()
       
   742 	{
       
   743 	RFile file;
       
   744 	TInt count = iFirstFile;
       
   745 
       
   746 	while (count < iFirstFile + iNumFiles)
       
   747 		{
       
   748 		TFileName nextFile;
       
   749 		FileNameGen(nextFile, count);
       
   750 		file.Open(iFs, nextFile, EFileWrite);
       
   751 		TInt size;
       
   752 		file.Size(size);
       
   753 		file.SetSize(size+10);
       
   754 		file.Close();	
       
   755 		count++;
       
   756 		}
       
   757 	}
       
   758 
       
   759 void CFileOperator::DoDeleteL()
       
   760 	{
       
   761 	TInt count = iFirstFile;
       
   762 	
       
   763 	while (count < iFirstFile + iNumFiles)
       
   764 		{
       
   765 		TFileName nextFile;
       
   766 		FileNameGen(nextFile, count);
       
   767 		iFs.Delete(nextFile);
       
   768 		count++;
       
   769 		}
       
   770 	}
       
   771 
       
   772 void CFileOperator::DoCreateDirL()
       
   773 	{
       
   774 	TInt count = iFirstFile;
       
   775 	
       
   776 	while (count < iFirstFile + iNumFiles)
       
   777 		{
       
   778 		TFileName nextFile;
       
   779 		FileNameGen(nextFile, count, EFalse);
       
   780 		iFs.MkDir(nextFile);
       
   781 		count++;
       
   782 		}
       
   783 	}
       
   784 
       
   785 void CFileOperator::DoRenameDirL()
       
   786 	{
       
   787 	TInt count = iFirstFile;
       
   788 	while (count < iFirstFile + iNumFiles)
       
   789 		{
       
   790 		TFileName newFile;
       
   791 		TFileName oldFile;
       
   792 		FileNameGen(oldFile, count, EFalse);
       
   793 		FileNameGen(newFile, count + iNumFiles, EFalse);
       
   794 		
       
   795 		iFs.Rename(oldFile, newFile);
       
   796 		count++;
       
   797 		}
       
   798 	}
       
   799 
       
   800 void CFileOperator::DoDeleteDirL()
       
   801 	{
       
   802 	TInt count = iFirstFile;
       
   803 	
       
   804 	while (count < iFirstFile + iNumFiles)
       
   805 		{
       
   806 		TFileName nextFile;
       
   807 		FileNameGen(nextFile, count, EFalse);
       
   808 		iFs.RmDir(nextFile);
       
   809 		count++;
       
   810 		}
       
   811 	}
       
   812 
       
   813 void CFileOperator::DoManyChangesOnSingleFileL()
       
   814 	{
       
   815 	TFileName fileName;
       
   816 	FileNameGen(fileName, 9999);
       
   817 	
       
   818 	RFile file;
       
   819 	_LIT8(KData, "a");
       
   820 	
       
   821 	for(TInt i = 0; i < iNumFiles; i++)
       
   822 		{
       
   823 		TInt offset = 0;
       
   824 		file.Open(iFs, fileName, EFileWrite);
       
   825 		file.Seek(ESeekEnd, offset);
       
   826 		file.Write(KData);
       
   827 		file.Flush();
       
   828 		file.Close();
       
   829 		}
       
   830 	}
       
   831 
       
   832 void CFileOperator::DoSmallChangesOnManyFilesL()
       
   833 	{
       
   834 	RFile file;
       
   835     _LIT8(KData, "a");
       
   836 	
       
   837 	for(TInt i = 0; i < iNumFiles; i++)
       
   838 		{
       
   839 		TFileName nextFile;
       
   840 		FileNameGen(nextFile, i);
       
   841 		file.Open(iFs, nextFile, EFileWrite);
       
   842 		file.Write(KData);
       
   843 		file.Flush();
       
   844 		file.Close();	
       
   845 		}
       
   846 	}
       
   847 
       
   848 void CFileOperator::DoMixedOperationsL()
       
   849 	{
       
   850 	// will perform 18*iNumFiles operations
       
   851 	RFile file;
       
   852 	TInt firstFile = iFirstFile;
       
   853 	TInt lastFile = iFirstFile + (2 * iNumFiles);
       
   854 	TInt firstDir = iFirstFile;
       
   855 	TInt lastDir = iFirstFile + iNumFiles;
       
   856 	
       
   857 	_LIT8(KData, "Some text.");
       
   858 
       
   859 	TInt i;
       
   860 	// Create Files - 2*iNumFiles Ops
       
   861 	// we create 2*iNumFiles files here so that we can ensure that at least iNumfiles ops are performed after the replace step
       
   862 	for (i = firstFile; i < lastFile; i++)
       
   863 		{
       
   864 		TFileName nextFile;
       
   865 		FileNameGen(nextFile, i);
       
   866 		file.Create(iFs, nextFile, EFileRead);
       
   867 		file.Close();	
       
   868 		}
       
   869 
       
   870 	// Create Directories - iNumFiles Ops
       
   871 	for (i = firstDir; i < lastDir; i++)
       
   872 		{
       
   873 		TFileName nextFile;
       
   874 		FileNameGen(nextFile, i, EFalse);
       
   875 		iFs.MkDir(nextFile);
       
   876 		}
       
   877 	
       
   878 	// Write - 2*iNumFiles Ops
       
   879 	for (i = firstFile; i < lastFile; i++)
       
   880 		{
       
   881 		TFileName nextFile;
       
   882 		FileNameGen(nextFile, i);
       
   883 		file.Open(iFs, nextFile, EFileWrite);
       
   884 		file.Write(KData);
       
   885 		file.Flush();
       
   886 		file.Close();
       
   887 		}
       
   888 
       
   889 	// Resize - 2*iNumFiles Ops
       
   890 	for (i = firstFile; i < lastFile; i++)
       
   891 		{
       
   892 		TFileName nextFile;
       
   893 		FileNameGen(nextFile, i);
       
   894 		file.Open(iFs, nextFile, EFileWrite);
       
   895 		TInt size;
       
   896 		file.Size(size);
       
   897 		file.SetSize(size+10);
       
   898 		file.Close();
       
   899 		}
       
   900 	
       
   901 	// Replace Files - iNumFiles Ops
       
   902 	for (i = firstFile; i < firstFile + iNumFiles; i++)
       
   903 		{
       
   904 		TFileName newFile;
       
   905 		TFileName oldFile;
       
   906 		FileNameGen(oldFile, i);
       
   907 		FileNameGen(newFile, i + iNumFiles);
       
   908 		iFs.Replace(oldFile, newFile);
       
   909 		}
       
   910 	firstFile += iNumFiles;
       
   911 	
       
   912 	// Rename Files - iNumFiles Ops
       
   913 	for (i = firstFile; i < lastFile; i++)
       
   914 		{
       
   915 		TFileName newFile;
       
   916 		TFileName oldFile;
       
   917 		FileNameGen(newFile, i - iNumFiles);
       
   918 		FileNameGen(oldFile, i);	
       
   919 		iFs.Rename(oldFile, newFile);
       
   920 		}
       
   921 	firstFile -= iNumFiles;
       
   922 	lastFile -= iNumFiles;
       
   923 	
       
   924 	// Delete Dirs - iNumFiles Ops
       
   925 	for (i = firstDir; i < lastDir; i++)
       
   926 		{
       
   927 		TFileName nextFile;
       
   928 		FileNameGen(nextFile, i, EFalse);
       
   929 		iFs.RmDir(nextFile);
       
   930 		}
       
   931 	
       
   932 	// Delete File - iNumFiles Ops
       
   933 	for (i = firstFile; i < lastFile; i++)
       
   934 		{
       
   935 		TFileName nextFile;
       
   936 		FileNameGen(nextFile, i);
       
   937 		iFs.Delete(nextFile);
       
   938 		}
       
   939 
       
   940 	// All-in-one - 7*iNumFiles Ops
       
   941 	for (i = firstFile; i < lastFile; i++)
       
   942 		{
       
   943 		TFileName nextFile;
       
   944 		FileNameGen(nextFile, i);
       
   945 		TFileName nextDir;
       
   946 		FileNameGen(nextDir, i, EFalse);
       
   947 		
       
   948 		iFs.MkDir(nextDir);
       
   949 		
       
   950 		file.Create(iFs, nextFile, EFileWrite);
       
   951 		file.Write(KData);
       
   952 		file.Flush();
       
   953 		TInt size;
       
   954 		file.Size(size);
       
   955 		file.SetSize(size+10);
       
   956 		file.Close();
       
   957 		
       
   958 		TFileName newName;
       
   959 		FileNameGen(newName, i + iNumFiles);
       
   960 		iFs.Rename(nextFile, newName);
       
   961 		
       
   962 		iFs.Delete(newName);
       
   963 		iFs.RmDir(nextDir);
       
   964 		}
       
   965 	}
       
   966 
       
   967 //==========================================================
       
   968 
       
   969 CNotifyOperator::CNotifyOperator(const TTestSetting& aSetting, RSemaphore* aSmphFT, RSemaphore* aSmphNT, CTimerLogger* aLogger)
       
   970 	{
       
   971 	iNumFiles = aSetting.iNumFiles;
       
   972 	iOption = aSetting.iOption;
       
   973 	iCurrentOp = aSetting.iOperationList;
       
   974 	iLogger = aLogger;
       
   975 	iSmphS = aSmphFT;
       
   976 	iSmphW = aSmphNT;
       
   977 	}
       
   978 
       
   979 CNotifyOperator::~CNotifyOperator()
       
   980 	{
       
   981 	}
       
   982 
       
   983 // start operations in notification thread
       
   984 // this is the main function called in the thread,
       
   985 // it creates notification watcher, requests notification, and check test result
       
   986 void CNotifyOperator::StartOperationL()
       
   987 	{
       
   988 	CNotifyWatcher* notifyWatcher = CNotifyWatcher::NewL(iNumFiles, iOption, *iCurrentOp, iLogger);
       
   989 	CleanupStack::PushL(notifyWatcher);
       
   990 	CTestStopper* stopper = new(ELeave) CTestStopper();
       
   991 	CleanupStack::PushL(stopper);
       
   992 	
       
   993 	CActiveScheduler::Add(notifyWatcher);
       
   994 	CActiveScheduler::Add(stopper);
       
   995 	
       
   996 	while (*iCurrentOp != EOpEnd)
       
   997 		{
       
   998 		iSmphW->Wait();	// wait for file thread finishing preparation for the current file operation.
       
   999 		
       
  1000 		notifyWatcher->FullDirectoryScanL(notifyWatcher->iEntries);
       
  1001 		notifyWatcher->RequestNotification();
       
  1002 		stopper->StartWaitingForFile();
       
  1003 		
       
  1004 		iSmphS->Signal();	// Signal file thread that the notifications are requested, ready to receive
       
  1005 		
       
  1006 		CActiveScheduler::Start();
       
  1007 		////////////////////////////////
       
  1008 		// receiving notifications... //
       
  1009 		////////////////////////////////
       
  1010 		
       
  1011 		notifyWatcher->HandleNotification(ETrue); // handle for the last time
       
  1012 		
       
  1013 		LogTestResult(notifyWatcher->iCounter, notifyWatcher->iMeanCounter, notifyWatcher->iOverflowCounter);
       
  1014 		
       
  1015 		if(iOption & EReportChg)
       
  1016 		    {
       
  1017 			TestChangeReport(notifyWatcher->iRecords.Count());
       
  1018 		    }
       
  1019 		
       
  1020 		if (!gPerfMeasure)
       
  1021 		    {
       
  1022 		    TInt id = iOption & KNotifyTreadIdMask;
       
  1023             if (iOption & EMultiNoti2)
       
  1024                 {
       
  1025                 if ( *iCurrentOp == EOpCreate ||
       
  1026                     (id % 4 == 0 && (*iCurrentOp == EOpRename || *iCurrentOp == EOpReplace)) ||
       
  1027                     (id % 4 == 1 && *iCurrentOp == EOpChgAttr) || 
       
  1028                     (id % 4 == 2 && (*iCurrentOp == EOpResize || *iCurrentOp == EOpWrite)) ||
       
  1029                     (id % 4 == 3 && *iCurrentOp == EOpDelete))
       
  1030                     {
       
  1031                     SAFETEST2(notifyWatcher->iCounter, iNumFiles, id);
       
  1032                     }
       
  1033                 }
       
  1034             else
       
  1035                 {
       
  1036                 SAFETEST2(notifyWatcher->iCounter, iNumFiles, id);
       
  1037                 }
       
  1038 		    }
       
  1039 		
       
  1040 		iSmphS->Signal();	// Signal file thread that all notifications are received
       
  1041 		
       
  1042 		iCurrentOp++;
       
  1043 		
       
  1044 		notifyWatcher->Reset(*iCurrentOp);
       
  1045 		if ((*iCurrentOp == EOpManyFiles) || (*iCurrentOp == EOpManyChanges))
       
  1046 			{
       
  1047 			iNumFiles += 1000;
       
  1048 			}
       
  1049 		else if (*iCurrentOp == EOpMixed)
       
  1050 		    {
       
  1051 		    iNumFiles += 50;
       
  1052 		    }
       
  1053 		}
       
  1054 
       
  1055 	CleanupStack::PopAndDestroy(2);
       
  1056 	
       
  1057 	}
       
  1058 
       
  1059 // Write log and print the notification numbers using iLogger
       
  1060 void CNotifyOperator::LogNotificationNumbers(TInt aNumNoti, TInt aNumIter, TInt aNumOverflow)
       
  1061 	{
       
  1062 	TBuf<100> buf;
       
  1063 	
       
  1064 	if (iOption & EEnhanced)
       
  1065 		{	
       
  1066 		if (aNumOverflow > 0)
       
  1067 			{
       
  1068 			buf.AppendFormat(_L("Buffer overflow: %d overflow notifications received."), aNumOverflow, aNumNoti);
       
  1069 			iLogger->LogAndPrint(buf);
       
  1070 			buf.Zero();
       
  1071 			}
       
  1072 		
       
  1073 		TReal mean = static_cast<TReal>(aNumNoti)/aNumIter;
       
  1074 		buf.AppendFormat(_L("%.2f mean enhanced notifications per iteration."), mean);	
       
  1075 		iLogger->LogAndPrint(buf);
       
  1076 		buf.Zero();
       
  1077 		}
       
  1078 	
       
  1079 	buf.AppendFormat(_L("%d notifications received overall."), aNumNoti);
       
  1080 	iLogger->LogAndPrint(buf);
       
  1081 	}
       
  1082 
       
  1083 // Write log and print the test reault
       
  1084 void CNotifyOperator::LogTestResult(TInt aCounter, TInt aMeanCounter, TInt aOFCounter)
       
  1085     {
       
  1086     if (iOption & EMultiNoti2)
       
  1087         {
       
  1088         TInt id = iOption & KNotifyTreadIdMask;
       
  1089         if ( *iCurrentOp == EOpCreate || 
       
  1090             (id % 4 == 0 && (*iCurrentOp == EOpRename || *iCurrentOp == EOpReplace)) || 
       
  1091             (id % 4 == 1 && *iCurrentOp == EOpChgAttr) || 
       
  1092             (id % 4 == 2 && (*iCurrentOp == EOpWrite || *iCurrentOp == EOpResize)) ||
       
  1093             (id % 4 == 3 && *iCurrentOp == EOpDelete))
       
  1094             {
       
  1095             iLogger->LogTestStepTime(*iCurrentOp, iNumFiles);
       
  1096             LogNotificationNumbers(aCounter, aMeanCounter, aOFCounter);
       
  1097             }
       
  1098         else 
       
  1099             iLogger->LogAndPrint(_L("File operation not tested - time: 0 ms"));
       
  1100         }
       
  1101     else if (iOption & EPlugin)
       
  1102         {
       
  1103         if (*iCurrentOp == EOpChgAttr || *iCurrentOp == EOpWrite || *iCurrentOp == EOpResize)
       
  1104             iLogger->LogAndPrint(_L("File operation not tested - time: 0 ms"));
       
  1105         else
       
  1106             {
       
  1107             iLogger->LogTestStepTime(*iCurrentOp, iNumFiles);
       
  1108             LogNotificationNumbers(aCounter, aMeanCounter, aOFCounter);
       
  1109             } 
       
  1110         }
       
  1111     else
       
  1112         {
       
  1113         iLogger->LogTestStepTime(*iCurrentOp, iNumFiles);
       
  1114         LogNotificationNumbers(aCounter, aMeanCounter, aOFCounter);
       
  1115         }
       
  1116     }
       
  1117 
       
  1118 // When change report enabled, check the number of changes we detected
       
  1119 void CNotifyOperator::TestChangeReport(TInt aNumChanges)
       
  1120     {
       
  1121     TBuf<100> buf;
       
  1122     buf.AppendFormat(_L("%d file changes detected.\r\n"), aNumChanges);
       
  1123     iLogger->LogAndPrint(buf);
       
  1124     
       
  1125     TInt id = iOption & KNotifyTreadIdMask;
       
  1126     if (iOption & EEnhanced)
       
  1127         {
       
  1128         if (iOption & EMultiNoti2)
       
  1129             {
       
  1130             if ( *iCurrentOp == EOpCreate ||
       
  1131                 (id % 4 == 0 && (*iCurrentOp == EOpRename || *iCurrentOp == EOpReplace)) ||
       
  1132                 (id % 4 == 1 && *iCurrentOp == EOpChgAttr) || 
       
  1133                 (id % 4 == 2 && (*iCurrentOp == EOpResize || *iCurrentOp == EOpWrite)) ||
       
  1134                 (id % 4 == 3 && *iCurrentOp == EOpDelete))
       
  1135                 {
       
  1136                 SAFETEST2(aNumChanges, iNumFiles, id);
       
  1137                 }
       
  1138             }
       
  1139         else if (!(iOption & EBigBuffer))
       
  1140             {
       
  1141             // not testing this case, because the number of file changes detected 
       
  1142             // could varies depend on when notifications are received
       
  1143             }
       
  1144         else if (*iCurrentOp == EOpMixed)
       
  1145             {
       
  1146             SAFETEST2(aNumChanges, (18*iNumFiles), id); // On cached drives, the number of write notification could vary.
       
  1147             }
       
  1148         else
       
  1149             {
       
  1150             SAFETEST2(aNumChanges, iNumFiles, id);
       
  1151             }
       
  1152         }
       
  1153     else if (iOption & EOriginal)
       
  1154         {
       
  1155         if ((*iCurrentOp == EOpManyChanges) || (*iCurrentOp == EOpMixed))
       
  1156             {
       
  1157             // not testing this case, because the number of file changes detected 
       
  1158             // could varies depend on when notifications are received
       
  1159             }
       
  1160         else if ((*iCurrentOp == EOpReplace) || (*iCurrentOp == EOpRename) || (*iCurrentOp == EOpRenameDir))
       
  1161             {
       
  1162             SAFETEST2(aNumChanges, (2*iNumFiles), id);
       
  1163             }
       
  1164         else
       
  1165             {
       
  1166             SAFETEST2(aNumChanges, iNumFiles, id);
       
  1167             }
       
  1168         }
       
  1169     else if (iOption & EPlugin)
       
  1170         {
       
  1171         if (*iCurrentOp == EOpCreate || *iCurrentOp == EOpReplace || *iCurrentOp == EOpRename || 
       
  1172                 *iCurrentOp == EOpDelete || *iCurrentOp == EOpRenameDir)
       
  1173             {
       
  1174             SAFETEST2(aNumChanges, iNumFiles, id);
       
  1175             }
       
  1176         else if (*iCurrentOp == EOpMixed)
       
  1177             {
       
  1178             SAFETEST2(aNumChanges, (8*iNumFiles), id); // only part of operations can be notified
       
  1179             }
       
  1180         // Other cases are not testable.
       
  1181         }
       
  1182     }
       
  1183 
       
  1184 //===========================================================
       
  1185 	
       
  1186 CNotifyWatcher::CNotifyWatcher(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger) 
       
  1187 : CActive(CActive::EPriorityStandard), iCounter(0), iMeanCounter(0), iOverflowCounter(0), iCurrentOp(aCurrentOp),
       
  1188 iNumFiles(aNumFiles), iOption(aOption), iEntries(aNumFiles), iRecords(aNumFiles), iLogger(aLogger)
       
  1189 	{
       
  1190 	}
       
  1191 
       
  1192 CNotifyWatcher::~CNotifyWatcher()
       
  1193 	{
       
  1194 	Cancel();
       
  1195 	delete iNotify;
       
  1196 
       
  1197     iFs.DismountPlugin(KPluginName);
       
  1198     iFs.RemovePlugin(KPluginName);
       
  1199 	
       
  1200 	iFs.Close();
       
  1201 	iEntries.Close();
       
  1202 	iRecords.Close();
       
  1203 	}
       
  1204 
       
  1205 CNotifyWatcher* CNotifyWatcher::NewL(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger)
       
  1206 	{
       
  1207 	CNotifyWatcher* self = new(ELeave) CNotifyWatcher(aNumFiles, aOption, aCurrentOp, aLogger);
       
  1208 	CleanupStack::PushL(self);
       
  1209 	self->ConstructL();
       
  1210 	CleanupStack::Pop(self);
       
  1211 	return self;
       
  1212 	}
       
  1213 
       
  1214 void CNotifyWatcher::ConstructL()
       
  1215 	{
       
  1216 	iFs.Connect();
       
  1217 	
       
  1218 	if (iOption & EEnhanced)
       
  1219 		{
       
  1220 		TInt bufferSize;
       
  1221 		if(iOption & EBigBuffer)
       
  1222 			{
       
  1223 			bufferSize = KMinNotificationBufferSize * iNumFiles;
       
  1224 			if (iCurrentOp == EOpMixed)
       
  1225 				bufferSize = bufferSize * 18;
       
  1226 			}
       
  1227 		else
       
  1228 			bufferSize = KMinNotificationBufferSize;
       
  1229 		
       
  1230 		iNotify = CFsNotify::NewL(iFs, bufferSize);
       
  1231 		}
       
  1232 	else
       
  1233 		iNotify = NULL;
       
  1234 
       
  1235 	if (iOption& EPlugin)
       
  1236 		{
       
  1237 		TInt r = iFs.AddPlugin(KPluginName);
       
  1238 		test(r == KErrNone || r == KErrAlreadyExists);
       
  1239 		if (r != KErrAlreadyExists)
       
  1240 		    {
       
  1241 		    r = iFs.MountPlugin(KPluginName);
       
  1242 		    test(r == KErrNone);
       
  1243 		    }
       
  1244 		}
       
  1245 	
       
  1246 	FullDirectoryScanL(iEntries);
       
  1247 	iRecords.Reset();
       
  1248 	}
       
  1249 
       
  1250 // reset certain members so that we can do next test step
       
  1251 void CNotifyWatcher::Reset(TUint aOp)
       
  1252 	{
       
  1253 	iCurrentOp = aOp;
       
  1254 	iRecords.Reset();
       
  1255 	iCounter = 0;
       
  1256 	iOverflowCounter = 0;
       
  1257 	iMeanCounter = 0;
       
  1258 	if ((aOp == EOpManyFiles) || (aOp == EOpManyChanges))
       
  1259 		iNumFiles += 1000;
       
  1260 	}
       
  1261 
       
  1262 // perform a full dir scan
       
  1263 void CNotifyWatcher::FullDirectoryScanL(RArray<TEntry>& aArray)
       
  1264 	{
       
  1265 	aArray.Reset();
       
  1266 	
       
  1267 	CDir* list;
       
  1268 	iFs.GetDir(gTestPath, KEntryAttMaskSupported, ESortByName, list);
       
  1269 	
       
  1270 	if (!list)
       
  1271 	    return;
       
  1272 	
       
  1273 	CleanupStack::PushL(list);
       
  1274 	
       
  1275 	for (TInt i = 0; i < list->Count(); i++)
       
  1276 		{
       
  1277 		TEntry en ((*list)[i]);
       
  1278 		aArray.AppendL(en);
       
  1279 		}
       
  1280 	
       
  1281 	CleanupStack::PopAndDestroy();
       
  1282 	}
       
  1283 
       
  1284 // find out what has changed in test path, and save the changes in iRecord
       
  1285 void CNotifyWatcher::MakeChangeRecordL(RArray<TEntry>& aArray)
       
  1286 	{
       
  1287 	TInt num = aArray.Count();
       
  1288 	TInt r,i;
       
  1289 	for (i = 0; i < num; i++)
       
  1290 		{
       
  1291 		TInt index = iEntries.Find(aArray[i], CompareEntryName);
       
  1292 		SAFETEST1((index == KErrNotFound || index >= 0), (iOption & KNotifyTreadIdMask));
       
  1293 		
       
  1294 		TFileName name(aArray[i].iName);
       
  1295 		
       
  1296 		if (index == KErrNotFound)
       
  1297 			{
       
  1298 			r = iRecords.Append(name);
       
  1299 			SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1300 			}
       
  1301 		else
       
  1302 			{
       
  1303 			if (!CompareEntry(iEntries[index], aArray[i]))
       
  1304 				{
       
  1305 				r = iRecords.Append(name);
       
  1306 				SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1307 				}
       
  1308 			iEntries.Remove(index);
       
  1309 			}
       
  1310 		}
       
  1311 	
       
  1312 	num = iEntries.Count();
       
  1313 	
       
  1314 	for (i = 0; i < num; i++)
       
  1315 		{
       
  1316 		TFileName name(iEntries[i].iName);
       
  1317 		r = iRecords.Append(name);
       
  1318 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1319 		}
       
  1320 	
       
  1321 	iEntries.Reset();
       
  1322 	num = aArray.Count();
       
  1323 	for (i = 0; i < num; i++)
       
  1324 		{
       
  1325 		TEntry en (aArray[i]);
       
  1326 		iEntries.AppendL(en);
       
  1327 		}
       
  1328 	}
       
  1329 
       
  1330 
       
  1331 TBool CNotifyWatcher::CompareEntry(const TEntry& aEntry1, const TEntry& aEntry2)
       
  1332 	{
       
  1333 	// we don't compare name, because names are compared by CompareEntryName() already
       
  1334 	if ((aEntry1.iAtt == aEntry2.iAtt) && (aEntry1.iModified == aEntry2.iModified) 
       
  1335 			&& (aEntry1.iSize == aEntry2.iSize) && (aEntry1.iType == aEntry2.iType))
       
  1336 		return ETrue;
       
  1337 	
       
  1338 	return EFalse;
       
  1339 	}
       
  1340 
       
  1341 // add 100 filters for enhanced notification test case
       
  1342 void CNotifyWatcher::AddLotsOfFilters()
       
  1343 	{
       
  1344 	for (TInt i = 0; i < 100; i++)
       
  1345 		{
       
  1346 		TFileName path;
       
  1347 		path.Copy(gTestPath);
       
  1348 		path.Append('*');
       
  1349 		TFileName file;
       
  1350 		file.AppendFormat(_L("*.%3d"), i);
       
  1351 		TInt r = iNotify->AddNotification((TUint)TFsNotification::EAllOps, gTestPath, file);
       
  1352 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1353 		}
       
  1354 	}
       
  1355 
       
  1356 void CNotifyWatcher::RequestNotification()
       
  1357 	{
       
  1358 	switch (iOption & KNotifyOptionMask)
       
  1359 		{
       
  1360 		case EEnhanced:
       
  1361 			RequestNotificationEnhanced();
       
  1362 			break;
       
  1363 		case EOriginal:
       
  1364 			RequestNotificationOriginal();
       
  1365 			break;
       
  1366 		case EPlugin:
       
  1367 			RequestNotificationPlugin();
       
  1368 			break;
       
  1369 		case ENoNotify:
       
  1370 		default:
       
  1371 			return;
       
  1372 		}
       
  1373 	}
       
  1374 
       
  1375 // request notification using enhanced notification
       
  1376 void CNotifyWatcher::RequestNotificationEnhanced()
       
  1377 	{
       
  1378 	if (iOption & EBigFilter)
       
  1379 		{
       
  1380 		AddLotsOfFilters();
       
  1381 		}
       
  1382 	
       
  1383 	TFileName path;
       
  1384 	path.Copy(gTestPath);
       
  1385 	path.Append('*');
       
  1386 	TBuf<3> file = _L("*");
       
  1387 	
       
  1388 	if (iOption & EMultiNoti1)
       
  1389 		{
       
  1390 		TInt r = iNotify->AddNotification(TFsNotification::ECreate, path, file); // Create & replace
       
  1391 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1392 		r = iNotify->AddNotification(TFsNotification::ERename, path, file);	// Change Attribute
       
  1393 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1394 		r = iNotify->AddNotification(TFsNotification::EAttribute, path, file); // Rename
       
  1395 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1396 		r = iNotify->AddNotification(TFsNotification::EFileChange, path, file); // Write & Setsize
       
  1397 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1398 		r = iNotify->AddNotification(TFsNotification::EDelete, path, file); // Delete
       
  1399 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1400 		}
       
  1401 	else if (iOption & EMultiNoti2)
       
  1402 		{
       
  1403 		TInt r = iNotify->AddNotification(TFsNotification::ECreate, path, file); // Create & replace
       
  1404 		TInt id = iOption & KNotifyTreadIdMask;
       
  1405 		
       
  1406 		switch (id%4)
       
  1407 			{
       
  1408 			case 0:
       
  1409 				r = iNotify->AddNotification(TFsNotification::ERename, path, file);	// Change Attribute
       
  1410 				SAFETEST2(r, KErrNone, id);
       
  1411 				break;
       
  1412 			case 1:
       
  1413 				r = iNotify->AddNotification(TFsNotification::EAttribute, path, file); // Rename
       
  1414 				SAFETEST2(r, KErrNone, id);
       
  1415 				break;
       
  1416 			case 2:
       
  1417 				r = iNotify->AddNotification(TFsNotification::EFileChange, path, file); // Write & Setsize
       
  1418 				SAFETEST2(r, KErrNone, id);
       
  1419 				break;
       
  1420 			case 3:
       
  1421 				r = iNotify->AddNotification(TFsNotification::EDelete, path, file); // Delete
       
  1422 				SAFETEST2(r, KErrNone, id);
       
  1423 				break;
       
  1424 			default:
       
  1425 				break;
       
  1426 			}
       
  1427 		}
       
  1428 	else
       
  1429 		{
       
  1430 		TInt r = iNotify->AddNotification((TUint)TFsNotification::EAllOps, path, file);
       
  1431 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1432 		}
       
  1433 	
       
  1434 	TInt r = iNotify->RequestNotifications(iStatus);
       
  1435 	SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1436 	
       
  1437 	SetActive();
       
  1438 	}
       
  1439 
       
  1440 // request notification using original notification
       
  1441 void CNotifyWatcher::RequestNotificationOriginal()
       
  1442 	{
       
  1443 	iFs.NotifyChange(ENotifyAll, iStatus, gTestPath);
       
  1444 	SetActive();
       
  1445 	}
       
  1446 
       
  1447 void CNotifyWatcher::HandleNotification(TBool aLastTime)
       
  1448 	{
       
  1449 	switch (iOption & KNotifyOptionMask)
       
  1450 		{
       
  1451 		case EEnhanced:
       
  1452 			HandleNotificationEnhanced(aLastTime);
       
  1453 			break;
       
  1454 		case EOriginal:
       
  1455 			HandleNotificationOriginal(aLastTime);
       
  1456 			break;
       
  1457 		case EPlugin:
       
  1458 			HandleNotificationPlugin(aLastTime);
       
  1459 			break;
       
  1460 		case ENoNotify:
       
  1461 		default:
       
  1462 			return;
       
  1463 		}
       
  1464 	
       
  1465 	if(aLastTime)
       
  1466 		{
       
  1467 		iLogger->MeasureEnd();
       
  1468 		RDebug::Print(_L("Timing ended..."));
       
  1469 		Cancel();
       
  1470 		}
       
  1471 	}
       
  1472 
       
  1473 // handle enhanced notification
       
  1474 void CNotifyWatcher::HandleNotificationEnhanced(TBool aLastTime)
       
  1475 	{
       
  1476 	TInt num = iCounter;
       
  1477 	iMeanCounter++;
       
  1478 	
       
  1479 	TFsNotification::TFsNotificationType type;
       
  1480 	const TFsNotification* notification;
       
  1481 	
       
  1482 	while((notification = iNotify->NextNotification())!= NULL)
       
  1483 		{	
       
  1484 		iCounter++;
       
  1485 		type = notification->NotificationType();
       
  1486 		if (iOption & EBigBuffer)
       
  1487 			{
       
  1488 			SAFETEST1((type & OpNotifyMapping(iOption, iCurrentOp)), (iOption & KNotifyTreadIdMask));
       
  1489 			}
       
  1490 		else
       
  1491 			{
       
  1492 			SAFETEST1((type & (OpNotifyMapping(iOption, iCurrentOp) | TFsNotification::EOverflow)), (iOption & KNotifyTreadIdMask));
       
  1493 			}
       
  1494 		
       
  1495       if(iOption & EReportChg)
       
  1496             {
       
  1497             if (type & TFsNotification::EOverflow)
       
  1498                 {
       
  1499                 iOverflowCounter++;
       
  1500                 RArray<TEntry> newEntries;
       
  1501                 FullDirectoryScanL(newEntries);
       
  1502                 MakeChangeRecordL(newEntries);
       
  1503                 newEntries.Close();
       
  1504                 }
       
  1505             else
       
  1506                 {
       
  1507                 TPtrC ptr;
       
  1508                 notification->Path(ptr);
       
  1509                 TFileName name;
       
  1510                 name.Copy(ptr);
       
  1511                 TInt r = iRecords.Append(name);
       
  1512                 SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1513                 }
       
  1514             }
       
  1515 		}
       
  1516 	
       
  1517 	if (aLastTime)
       
  1518 		{
       
  1519 		if (num == iCounter) // no new notification so this iteration doesn't count
       
  1520 		    {
       
  1521 		    iMeanCounter--;
       
  1522 		    }
       
  1523 		return;
       
  1524 		}
       
  1525 	
       
  1526 	iNotify->RequestNotifications(iStatus);
       
  1527 	SetActive();
       
  1528 	}
       
  1529 
       
  1530 // handle original notification
       
  1531 void CNotifyWatcher::HandleNotificationOriginal(TBool aLastTime)
       
  1532 	{
       
  1533 	iCounter++;
       
  1534 	
       
  1535 	if (iOption & EReportChg)
       
  1536 		{
       
  1537 		RArray<TEntry> newEntries;
       
  1538 		FullDirectoryScanL(newEntries);
       
  1539 		MakeChangeRecordL(newEntries);
       
  1540 		newEntries.Close();
       
  1541 		}
       
  1542 	
       
  1543 	if (aLastTime)
       
  1544 	    {
       
  1545 	    iCounter--; // the last time this function is called is not a notification.
       
  1546 		return;
       
  1547 	    }
       
  1548 
       
  1549 	RequestNotificationOriginal();
       
  1550 	}
       
  1551 
       
  1552 // reset the iPluginStatusPkg, so that we can request notification again
       
  1553 void CNotifyWatcher::ResetMdsFSPStatus()
       
  1554     {
       
  1555     TMdsFSPStatus& status = iPluginStatusPkg();
       
  1556 
       
  1557     status.iDriveNumber = 0;
       
  1558     status.iFileEventType = EMdsFileUnknown;
       
  1559     status.iFileName.Zero();
       
  1560     status.iNewFileName.Zero();
       
  1561     status.iProcessId = TUid::Null();
       
  1562     }
       
  1563 
       
  1564 // request notification using nokia MDS plugin
       
  1565 void CNotifyWatcher::RequestNotificationPlugin()
       
  1566     {
       
  1567     TInt r = iPlugin.Open(iFs, KMdsFSPluginPosition);
       
  1568     SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
       
  1569     iPlugin.AddNotificationPath(gTestPath);
       
  1570     
       
  1571     iPlugin.Enable();  
       
  1572     ResetMdsFSPStatus();
       
  1573     iPlugin.RegisterNotification(iPluginStatusPkg, iStatus);
       
  1574     SetActive();
       
  1575     }
       
  1576 
       
  1577 // handle notifications from plugin
       
  1578 void CNotifyWatcher::HandleNotificationPlugin(TBool aLastTime)
       
  1579 	{
       
  1580 	if (aLastTime)
       
  1581 	    return;
       
  1582 
       
  1583 	if (iOption & EReportChg)
       
  1584 	    {
       
  1585 	    TMdsFSPStatus& status = iPluginStatusPkg();
       
  1586 	    TFileName name;
       
  1587 	    name.Copy(status.iFileName);
       
  1588 	    iRecords.Append(name);
       
  1589 	    if (iCurrentOp != EOpMixed)
       
  1590 	        {
       
  1591 	        TInt type = status.iFileEventType;
       
  1592 	        SAFETEST1(((TUint)type == OpNotifyMapping(iOption, iCurrentOp)), (iOption & KNotifyTreadIdMask));
       
  1593 	        }
       
  1594 	    }
       
  1595 	
       
  1596     iCounter++;
       
  1597     ResetMdsFSPStatus();
       
  1598     iPlugin.RegisterNotification(iPluginStatusPkg, iStatus);
       
  1599     SetActive();
       
  1600 	}
       
  1601 
       
  1602 // cancel request
       
  1603 void CNotifyWatcher::DoCancel()
       
  1604 	{
       
  1605 	switch (iOption & KNotifyOptionMask)
       
  1606 		{
       
  1607 		case EEnhanced:
       
  1608 			iNotify->CancelNotifications(iStatus);
       
  1609 			iNotify->RemoveNotifications();
       
  1610 			// not breaking here as the Enhanced may change to Original if Overflow
       
  1611 		case EOriginal:
       
  1612 			iFs.NotifyChangeCancel(iStatus);
       
  1613 			break;
       
  1614 		case EPlugin:
       
  1615             iPlugin.Disable();
       
  1616 		    iPlugin.NotificationCancel();
       
  1617 		    iPlugin.Close();
       
  1618 			break;
       
  1619 		case ENoNotify:
       
  1620 		default:
       
  1621 			return;
       
  1622 		}
       
  1623 	}
       
  1624 
       
  1625 void CNotifyWatcher::RunL()
       
  1626 	{	
       
  1627 	HandleNotification(EFalse);
       
  1628 	}
       
  1629 
       
  1630 //========================================================================
       
  1631 
       
  1632 CTestStopper::CTestStopper()
       
  1633 : CActive(EPriorityLow)
       
  1634 	{
       
  1635 	iFs.Connect();
       
  1636 	iTestEndFile.Append(gLogFilePath);
       
  1637 	iTestEndFile.Append(_L("test.End"));
       
  1638 	}
       
  1639 
       
  1640 CTestStopper::~CTestStopper()
       
  1641 	{
       
  1642 	Cancel();
       
  1643 	iFs.Close();
       
  1644 	}
       
  1645 
       
  1646 void CTestStopper::DoCancel()
       
  1647 	{
       
  1648 	iFs.NotifyChangeCancel(iStatus);
       
  1649 	}
       
  1650 
       
  1651 // stop the scheduler since the test is done
       
  1652 void CTestStopper::RunL()
       
  1653 	{
       
  1654 	CActiveScheduler::Stop();
       
  1655 	iFs.Delete(iTestEndFile);
       
  1656 	Cancel();
       
  1657 	}
       
  1658 
       
  1659 // start waiting for "test.end" file
       
  1660 void CTestStopper::StartWaitingForFile()
       
  1661 	{
       
  1662 	iFs.NotifyChange(ENotifyAll,iStatus,iTestEndFile);
       
  1663 	SetActive();
       
  1664 	}