os/kernelhwsrv/kerneltest/f32test/bench/t_notify_perf_impl.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	// we don't check attributes when creating files, because dir scan sometimes returns file
  1335 	// entries before attributes being flushed, and we don't care about it in this test case.
  1336 	// we also don't check the modified time for all the test cases expect replacing test, 
  1337 	// because dir scan sometimes returns file entries before time being flushed, 
  1338 	// and we don't care about it as well.
  1339 	// For replacing test, we check modification time, because it's the way we distinguish the old and new files.
  1340 	if (iCurrentOp == EOpCreate)
  1341 	    {
  1342 	    if ((aEntry1.iSize == aEntry2.iSize) && (aEntry1.iType == aEntry2.iType))
  1343             return ETrue;
  1344 	    }
  1345 	else if (iCurrentOp == EOpReplace || iCurrentOp == EOpManyFiles || iCurrentOp == EOpManyChanges || iCurrentOp == EOpMixed)
  1346 	    {
  1347         if ((aEntry1.iAtt == aEntry2.iAtt) && (aEntry1.iModified == aEntry2.iModified) 
  1348                 && (aEntry1.iSize == aEntry2.iSize) && (aEntry1.iType == aEntry2.iType))
  1349             return ETrue;
  1350 	    }
  1351 	else
  1352 	    {
  1353         if ((aEntry1.iAtt == aEntry2.iAtt) && (aEntry1.iSize == aEntry2.iSize) 
  1354                 && (aEntry1.iType == aEntry2.iType))
  1355             return ETrue;
  1356 	    }
  1357 	
  1358 	return EFalse;
  1359 	}
  1360 
  1361 // add 100 filters for enhanced notification test case
  1362 void CNotifyWatcher::AddLotsOfFilters()
  1363 	{
  1364 	for (TInt i = 0; i < 100; i++)
  1365 		{
  1366 		TFileName path;
  1367 		path.Copy(gTestPath);
  1368 		path.Append('*');
  1369 		TFileName file;
  1370 		file.AppendFormat(_L("*.%3d"), i);
  1371 		TInt r = iNotify->AddNotification((TUint)TFsNotification::EAllOps, gTestPath, file);
  1372 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1373 		}
  1374 	}
  1375 
  1376 void CNotifyWatcher::RequestNotification()
  1377 	{
  1378 	switch (iOption & KNotifyOptionMask)
  1379 		{
  1380 		case EEnhanced:
  1381 			RequestNotificationEnhanced();
  1382 			break;
  1383 		case EOriginal:
  1384 			RequestNotificationOriginal();
  1385 			break;
  1386 		case EPlugin:
  1387 			RequestNotificationPlugin();
  1388 			break;
  1389 		case ENoNotify:
  1390 		default:
  1391 			return;
  1392 		}
  1393 	}
  1394 
  1395 // request notification using enhanced notification
  1396 void CNotifyWatcher::RequestNotificationEnhanced()
  1397 	{
  1398 	if (iOption & EBigFilter)
  1399 		{
  1400 		AddLotsOfFilters();
  1401 		}
  1402 	
  1403 	TFileName path;
  1404 	path.Copy(gTestPath);
  1405 	path.Append('*');
  1406 	TBuf<3> file = _L("*");
  1407 	
  1408 	if (iOption & EMultiNoti1)
  1409 		{
  1410 		TInt r = iNotify->AddNotification(TFsNotification::ECreate, path, file); // Create & replace
  1411 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1412 		r = iNotify->AddNotification(TFsNotification::ERename, path, file);	// Change Attribute
  1413 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1414 		r = iNotify->AddNotification(TFsNotification::EAttribute, path, file); // Rename
  1415 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1416 		r = iNotify->AddNotification(TFsNotification::EFileChange, path, file); // Write & Setsize
  1417 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1418 		r = iNotify->AddNotification(TFsNotification::EDelete, path, file); // Delete
  1419 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1420 		}
  1421 	else if (iOption & EMultiNoti2)
  1422 		{
  1423 		TInt r = iNotify->AddNotification(TFsNotification::ECreate, path, file); // Create & replace
  1424 		TInt id = iOption & KNotifyTreadIdMask;
  1425 		
  1426 		switch (id%4)
  1427 			{
  1428 			case 0:
  1429 				r = iNotify->AddNotification(TFsNotification::ERename, path, file);	// Change Attribute
  1430 				SAFETEST2(r, KErrNone, id);
  1431 				break;
  1432 			case 1:
  1433 				r = iNotify->AddNotification(TFsNotification::EAttribute, path, file); // Rename
  1434 				SAFETEST2(r, KErrNone, id);
  1435 				break;
  1436 			case 2:
  1437 				r = iNotify->AddNotification(TFsNotification::EFileChange, path, file); // Write & Setsize
  1438 				SAFETEST2(r, KErrNone, id);
  1439 				break;
  1440 			case 3:
  1441 				r = iNotify->AddNotification(TFsNotification::EDelete, path, file); // Delete
  1442 				SAFETEST2(r, KErrNone, id);
  1443 				break;
  1444 			default:
  1445 				break;
  1446 			}
  1447 		}
  1448 	else
  1449 		{
  1450 		TInt r = iNotify->AddNotification((TUint)TFsNotification::EAllOps, path, file);
  1451 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1452 		}
  1453 	
  1454 	TInt r = iNotify->RequestNotifications(iStatus);
  1455 	SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1456 	
  1457 	SetActive();
  1458 	}
  1459 
  1460 // request notification using original notification
  1461 void CNotifyWatcher::RequestNotificationOriginal()
  1462 	{
  1463 	iFs.NotifyChange(ENotifyAll, iStatus, gTestPath);
  1464 	SetActive();
  1465 	}
  1466 
  1467 void CNotifyWatcher::HandleNotification(TBool aLastTime)
  1468 	{
  1469 	switch (iOption & KNotifyOptionMask)
  1470 		{
  1471 		case EEnhanced:
  1472 			HandleNotificationEnhanced(aLastTime);
  1473 			break;
  1474 		case EOriginal:
  1475 			HandleNotificationOriginal(aLastTime);
  1476 			break;
  1477 		case EPlugin:
  1478 			HandleNotificationPlugin(aLastTime);
  1479 			break;
  1480 		case ENoNotify:
  1481 		default:
  1482 			return;
  1483 		}
  1484 	
  1485 	if(aLastTime)
  1486 		{
  1487 		iLogger->MeasureEnd();
  1488 		RDebug::Print(_L("Timing ended..."));
  1489 		Cancel();
  1490 		}
  1491 	}
  1492 
  1493 // handle enhanced notification
  1494 void CNotifyWatcher::HandleNotificationEnhanced(TBool aLastTime)
  1495 	{
  1496 	TInt num = iCounter;
  1497 	iMeanCounter++;
  1498 	
  1499 	TFsNotification::TFsNotificationType type;
  1500 	const TFsNotification* notification;
  1501 	
  1502 	while((notification = iNotify->NextNotification())!= NULL)
  1503 		{	
  1504 		iCounter++;
  1505 		type = notification->NotificationType();
  1506 		if (iOption & EBigBuffer)
  1507 			{
  1508 			SAFETEST1((type & OpNotifyMapping(iOption, iCurrentOp)), (iOption & KNotifyTreadIdMask));
  1509 			}
  1510 		else
  1511 			{
  1512 			SAFETEST1((type & (OpNotifyMapping(iOption, iCurrentOp) | TFsNotification::EOverflow)), (iOption & KNotifyTreadIdMask));
  1513 			}
  1514 		
  1515       if(iOption & EReportChg)
  1516             {
  1517             if (type & TFsNotification::EOverflow)
  1518                 {
  1519                 iOverflowCounter++;
  1520                 RArray<TEntry> newEntries;
  1521                 FullDirectoryScanL(newEntries);
  1522                 MakeChangeRecordL(newEntries);
  1523                 newEntries.Close();
  1524                 }
  1525             else
  1526                 {
  1527                 TPtrC ptr;
  1528                 notification->Path(ptr);
  1529                 TFileName name;
  1530                 name.Copy(ptr);
  1531                 TInt r = iRecords.Append(name);
  1532                 SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1533                 }
  1534             }
  1535 		}
  1536 	
  1537 	if (aLastTime)
  1538 		{
  1539 		if (num == iCounter) // no new notification so this iteration doesn't count
  1540 		    {
  1541 		    iMeanCounter--;
  1542 		    }
  1543 		return;
  1544 		}
  1545 	
  1546 	iNotify->RequestNotifications(iStatus);
  1547 	SetActive();
  1548 	}
  1549 
  1550 // handle original notification
  1551 void CNotifyWatcher::HandleNotificationOriginal(TBool aLastTime)
  1552 	{
  1553 	iCounter++;
  1554 	
  1555 	if (iOption & EReportChg)
  1556 		{
  1557 		RArray<TEntry> newEntries;
  1558 		FullDirectoryScanL(newEntries);
  1559 		MakeChangeRecordL(newEntries);
  1560 		newEntries.Close();
  1561 		}
  1562 	
  1563 	if (aLastTime)
  1564 	    {
  1565 	    iCounter--; // the last time this function is called is not a notification.
  1566 		return;
  1567 	    }
  1568 
  1569 	RequestNotificationOriginal();
  1570 	}
  1571 
  1572 // reset the iPluginStatusPkg, so that we can request notification again
  1573 void CNotifyWatcher::ResetMdsFSPStatus()
  1574     {
  1575     TMdsFSPStatus& status = iPluginStatusPkg();
  1576 
  1577     status.iDriveNumber = 0;
  1578     status.iFileEventType = EMdsFileUnknown;
  1579     status.iFileName.Zero();
  1580     status.iNewFileName.Zero();
  1581     status.iProcessId = TUid::Null();
  1582     }
  1583 
  1584 // request notification using nokia MDS plugin
  1585 void CNotifyWatcher::RequestNotificationPlugin()
  1586     {
  1587     TInt r = iPlugin.Open(iFs, KMdsFSPluginPosition);
  1588     SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
  1589     iPlugin.AddNotificationPath(gTestPath);
  1590     
  1591     iPlugin.Enable();  
  1592     ResetMdsFSPStatus();
  1593     iPlugin.RegisterNotification(iPluginStatusPkg, iStatus);
  1594     SetActive();
  1595     }
  1596 
  1597 // handle notifications from plugin
  1598 void CNotifyWatcher::HandleNotificationPlugin(TBool aLastTime)
  1599 	{
  1600 	if (aLastTime)
  1601 	    return;
  1602 
  1603 	if (iOption & EReportChg)
  1604 	    {
  1605 	    TMdsFSPStatus& status = iPluginStatusPkg();
  1606 	    TFileName name;
  1607 	    name.Copy(status.iFileName);
  1608 	    iRecords.Append(name);
  1609 	    if (iCurrentOp != EOpMixed)
  1610 	        {
  1611 	        TInt type = status.iFileEventType;
  1612 	        SAFETEST1(((TUint)type == OpNotifyMapping(iOption, iCurrentOp)), (iOption & KNotifyTreadIdMask));
  1613 	        }
  1614 	    }
  1615 	
  1616     iCounter++;
  1617     ResetMdsFSPStatus();
  1618     iPlugin.RegisterNotification(iPluginStatusPkg, iStatus);
  1619     SetActive();
  1620 	}
  1621 
  1622 // cancel request
  1623 void CNotifyWatcher::DoCancel()
  1624 	{
  1625 	switch (iOption & KNotifyOptionMask)
  1626 		{
  1627 		case EEnhanced:
  1628 			iNotify->CancelNotifications(iStatus);
  1629 			iNotify->RemoveNotifications();
  1630 			// not breaking here as the Enhanced may change to Original if Overflow
  1631 		case EOriginal:
  1632 			iFs.NotifyChangeCancel(iStatus);
  1633 			break;
  1634 		case EPlugin:
  1635             iPlugin.Disable();
  1636 		    iPlugin.NotificationCancel();
  1637 		    iPlugin.Close();
  1638 			break;
  1639 		case ENoNotify:
  1640 		default:
  1641 			return;
  1642 		}
  1643 	}
  1644 
  1645 void CNotifyWatcher::RunL()
  1646 	{	
  1647 	HandleNotification(EFalse);
  1648 	}
  1649 
  1650 //========================================================================
  1651 
  1652 CTestStopper::CTestStopper()
  1653 : CActive(EPriorityLow)
  1654 	{
  1655 	iFs.Connect();
  1656 	iTestEndFile.Append(gLogFilePath);
  1657 	iTestEndFile.Append(_L("test.End"));
  1658 	}
  1659 
  1660 CTestStopper::~CTestStopper()
  1661 	{
  1662 	Cancel();
  1663 	iFs.Close();
  1664 	}
  1665 
  1666 void CTestStopper::DoCancel()
  1667 	{
  1668 	iFs.NotifyChangeCancel(iStatus);
  1669 	}
  1670 
  1671 // stop the scheduler since the test is done
  1672 void CTestStopper::RunL()
  1673 	{
  1674 	CActiveScheduler::Stop();
  1675 	iFs.Delete(iTestEndFile);
  1676 	Cancel();
  1677 	}
  1678 
  1679 // start waiting for "test.end" file
  1680 void CTestStopper::StartWaitingForFile()
  1681 	{
  1682 	iFs.NotifyChange(ENotifyAll,iStatus,iTestEndFile);
  1683 	SetActive();
  1684 	}