kerneltest/f32test/bench/t_notify_perf.h
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32test\bench\t_notify_perf.h
// 
//

#include <f32file.h>
#include <f32file_private.h>
#include <e32test.h>
#include <e32svr.h>
#include <hal.h>
#include <e32math.h>
#include <e32std.h>

// File operation made in test path to trigger notifications
enum TNotifyPerfTestOperations
	{
	// File Operations
	EOpEnd,			// indicates that a series of operations ended
	EOpCreate,
	EOpReplace,
	EOpChgAttr,
	EOpRename,
	EOpWrite,
	EOpResize,
	EOpDelete,
	EOpManyChanges,	// Large number changes to a single file 
	EOpManyFiles,	// Small changes to large number of files
	
	// Directory Operations
	EOpCreateDir,
	EOpRenameDir,
	EOpDeleteDir,
	
	// Mixed Operations
	EOpMixed		// A series of mixed operations involving both Files and Dirs
	};
	
enum TTestOptions
	{
	//////////////////////////////////////////////////////
	// Lowest 4 bit reserved for notification treads ID //
	//////////////////////////////////////////////////////
	
	// Test with a lot of filters for enhanced notification - 1st bit
	// set - on; unset - off
	EBigFilter	= 0x0010,
	
	// Whether perform full directory scan and save the file changes to a list - 2nd bit
	// set - perform; unset - not perform
	EReportChg	= 0x0020, 
	
	// Whether use big buffer for enhanced notification- 3rd bit
	// Set - big buffer(no overflow); unset - small(could have overflow)
	EBigBuffer	= 0x0040,
	
	// For multi clients test. Enhanced Notification Only!
	// Mode 1: set a variety of different notifications, same on each clients - 4th bit
	EMultiNoti1	= 0x0080,
	
	// For multi clients test. Enhanced Notification Only!
	// Mode 2: set a variety of different notifications, in which some are different on each clients, 
	// and some are same on each clients, only support upto 4 clients - 5th bit
	EMultiNoti2	= 0x0100,
	
	ENotPerfTestReserved6	= 0x0200, 
	ENotPerfTestReserved7	= 0x0400, 
	ENotPerfTestReserved8	= 0x0800, 
	
	// Notification type - 13th - 16th bits
	ENoNotify	= 0x1000,	// Test without notification
	EEnhanced	= 0x2000,	// Using enhanced notification APIs
	EOriginal	= 0x4000,	// Using original notification APIs
	EPlugin		= 0x8000,	// Using Nokia plug-in for notification
	};

// Note for Plugin Test
// the plugin test can only be run manually because the plugin is not available in KHS code base
// to run the test:
// 1. enable the MACRO above in the mmp
// 2. get a S60 environment
// 3. copy the MdsFileServerPlugin.ptx from the release(\Winscw or \Armv5 depend on what kind of test you want to run) 
//    directory of S60 to the equivalent folder of release directory of your epoc32
// 4. when build a rom, include the MdsFileServerPlugin.ptx file in the rom
// 5. then you can run
enum TMdsFSPOperation
    {
    EMdsFSPOpEnable,
    EMdsFSPOpDisable,
    EMdsFSPOpRegisterNotification,
    EMdsFSPOpAddNotificationPath,
    EMdsFSPOpRemoveNotificationPath,
    EMdsFSPOpAddIgnorePath,
    EMdsFSPOpRemoveIgnorePath,
    EMdsFSPOpNotificationCancel,
    };

class TMdsFSPStatus
    {
public:
    TInt iFileEventType;
    TInt iDriveNumber;
    TFileName iFileName;
    TFileName iNewFileName;
    TUid iProcessId;
    };

enum TMdsFileEventType
    {
    EMdsFileCreated,
    EMdsFileRenamed,
    EMdsFileModified,
    EMdsFileReplaced,
    EMdsFileDeleted,
    EMdsDriveFormatted,
    EMdsFileUnknown,
    EMdsDirRenamed
    };

typedef TPckgBuf<TMdsFSPStatus> TMdsFSPStatusPckg;

const TInt KMdsFSPluginPosition = 0x200071CD;
_LIT(KPluginName, "MdsFileServerPlugin");

// the list of operations to be conducted during a test case
const TUint KDefaultOpList[] = {EOpCreate, EOpReplace, EOpChgAttr, EOpRename, EOpWrite, EOpResize, EOpDelete, EOpEnd};
const TUint KDefaultOpListDir[] = {EOpCreateDir, EOpRenameDir, EOpDeleteDir, EOpEnd};

const TUint KManyChangesOpList[] = {EOpManyChanges, EOpManyChanges, EOpManyChanges, EOpManyChanges, EOpManyChanges, EOpEnd};
const TUint KManyFilesOpList[] = {EOpManyFiles, EOpManyFiles, EOpManyFiles, EOpManyFiles, EOpManyFiles, EOpEnd};
const TUint KMixedOpTestList[] = {EOpMixed, EOpMixed, EOpMixed, EOpMixed, EOpMixed, EOpEnd};

const TUint16 KNotifyOptionMask = 0xF000;
const TUint16 KNotifyTreadIdMask = 0x000F;

// default time scale for timer
const TUint KDefaultTimeScale = 1000; // 1ms
const TInt KMaxHeapSize = 0x1000000;

// used by SafeCheck
const TInt KNoThreadId = -1;

// a Controllor of whether measure time and write loggs;
extern TBool gPerfMeasure;

extern TFileName gTestPath;
extern TFileName gLogFilePath;

// Threads handles
extern RArray<RThread> gNotiThreads;
extern RThread gFileThread;

extern TBuf<50> gLogPostFix;

//-------------------------------------------------------------

class CTimerLogger;

// a wrapper for test settings
class TTestSetting
	{

public:
	TTestSetting();
	TTestSetting(TInt aNumFiles, TInt aNumCli, TUint16 aOpt, const TUint* aOpList);
	inline void Reset();
	
public:
	TInt iNumFiles;
	TInt iNumCli;
	TUint16 iOption;
	const TUint* iOperationList;
	
	};

// a wrapper of parameters for the main thread to pass into notification thread or file operation thread
struct TThreadParam
	{
	TTestSetting iSetting;
	RSemaphore* iSmphFT;	// Semophore used by File Thread for waiting for signals from Notification Threads
	RSemaphore* iSmphNT;	// Semophore used by Notification Threads for waiting for signals from File Thread
	CTimerLogger* iLogger;	// Logger used by Notification Threads;
	RPointerArray<CTimerLogger>* iLoggerArray;	// a pointer to an array of pointers to CTimmerLoggger
	};

// This is the controller of the plugin, it's a simplified copy of the plugin engine used in S60 internally
class CMdsPluginControl : public RPlugin
    {   
public:
    inline void RegisterNotification( TMdsFSPStatusPckg& aMdsFSPStatus, TRequestStatus& aStat);
    inline void AddNotificationPath( const TDesC& aPath );
    inline void RemoveNotificationPath( const TDesC& aPath );
    inline TInt Enable();
    inline TInt Disable();
    inline void NotificationCancel();
    };

// timer class, also responsible for writing logs
class CTimerLogger : public CBase
	{
	
public:	
	static CTimerLogger* NewL(const TFileName& aLogFile);
	~CTimerLogger();
	inline TInt MeasureStart();
	inline TInt MeasureEnd();
	inline TBool Timing();
	TInt Log(const TDesC& aDes, TBool aIsLine = ETrue);
	TInt LogAndPrint(const TDesC& aDes, TBool aIsLine = ETrue);
	TInt LogSettingDescription(const TInt aNumFile, const TInt aNumCli, const TUint16 aOption, TBool aNumOpVaries = EFalse);
	TInt LogTestStepTime(TUint aOp, TInt aNum);

private:
	CTimerLogger();
	void ConstructL(const TFileName& aLogFile);
	
private:
	TBool iTiming;
	TUint32 iTickNumber;
	TUint iTimeScale;
	TInt iTickPeriod;
	TFileName iLogFile;
	RFs iFs;
	};

// the conductor of test cases
class CTestExecutor : public CBase
	{

public:
	CTestExecutor(TTestSetting& aSetting);
	~CTestExecutor();
	
	inline void SetTestSetting(TTestSetting& aSetting);
	inline void LogDescription();
	
	void RunTestCaseL();
	static void KillAllTestThreads();
	
private:
	TTestSetting iTestSetting;
	
	};

// This class performs file operations
class CFileOperator : public CBase
	{
	
public:	
	CFileOperator(const TTestSetting& aSetting, RPointerArray<CTimerLogger>& aLoggerArray, RSemaphore* aSmphFT, RSemaphore* aSmphNT);
	~CFileOperator();
	void DoChangesL();
	
private:
	void DoCreateL();
	void DoReplaceL();
	void DoChangeAttL();
	void DoRenameL();
	void DoWriteL();
	void DoResizeL();
	void DoDeleteL();
	void DoCreateDirL();
	void DoRenameDirL();
	void DoDeleteDirL();
	void DoMixedOperationsL();
	
	void DoManyChangesOnSingleFileL();
	void DoSmallChangesOnManyFilesL();
	
	void MesureStartsAll();
	void WaitForSignalsAll();

	void TestStepPrepare(TUint aOp);
	void TestStepFinish(TUint aOp);
	
private:
	// test case will use the number iFirstFile and iNumFiles to generate test file names.
	// For example: 
	// if iFirstFile = 0 and iNumFiles = 100, the test files will be 0000.tst, 0001.tst ... 0099.tst
	// if iFirstFile = 21 and iNumFiles = 200, the test files will be 0021.tst, 0022.tst ... 0220.tst
	//
	// When doing rename or replace test, the new names for test will be the biggest existing file 
	// number + 1 to the number + iNumFiles.
	// As a result, in the case of if iFirstFile = 0 and iNumFiles = 100:
	// The exsting files should be 0000.tst ... 0099.tst
	// Rename or Replace test will use the new names 0100.tst ... 0199.tst to replace or rename the
	// existing files.
	TInt iFirstFile;
	
	// Number of files for operating.
	// Note: in "Large number changes to a single file" case, this indicates the number of changes made on the single file.
	TInt iNumFiles;
	TInt iNumCli;
	TUint16 iOption;
	const TUint* iCurrentOp;
	
	RPointerArray<CTimerLogger> iLoggers;
	RSemaphore* iSmphS;		// Use for signaling Notification threads
	RSemaphore* iSmphW;		// Use for waiting signal from Notification threads
	
	RFs iFs;
	};

// an operator to monitor notification watcher and test stopper
class CNotifyOperator : public CBase
	{
	
public:
	CNotifyOperator(const TTestSetting& aSetting, RSemaphore* aSmphFT, RSemaphore* aSmphNT, CTimerLogger* aLogger);
	~CNotifyOperator();
	
	void StartOperationL();
	
private:
	void LogNotificationNumbers(TInt aNumNoti, TInt aNumIter, TInt aNumOverflow);
	void LogTestResult(TInt aCounter, TInt aMeanCounter, TInt aOFCounter);
	void TestChangeReport(TInt aNumChanges);
	
private:
	TInt iNumFiles;
	TUint16 iOption;
	const TUint* iCurrentOp;
	
	CTimerLogger* iLogger;
	RSemaphore* iSmphS;	// Use for signaling file operation thread
	RSemaphore* iSmphW;	// Use for waiting signal from file operation thread
	};

// this class is responsible for handling notifications
class CNotifyWatcher : public CActive
	{
friend class CNotifyOperator;

public:
	static CNotifyWatcher* NewL(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger);
	~CNotifyWatcher();
	
	void DoCancel();
	void RunL();

	void RequestNotification();
	
	void Reset(TUint aOp);
	
private:
	CNotifyWatcher(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger);
	void ConstructL();

	void FullDirectoryScanL(RArray<TEntry>& aArray);
	void MakeChangeRecordL(RArray<TEntry>& aArray);
	TBool CompareEntry(const TEntry& aEntry1, const TEntry& aEntry2);
	
	void AddLotsOfFilters();
	
	void RequestNotificationEnhanced();
	void RequestNotificationOriginal();
	
	void HandleNotification(TBool aLastTime);
	
	void HandleNotificationEnhanced(TBool aLastTime);
	void HandleNotificationOriginal(TBool aLastTime);
	
	void ResetMdsFSPStatus();
	void RequestNotificationPlugin();
	void HandleNotificationPlugin(TBool aLastTime);
	
private:
	TInt iCounter;
	TInt iMeanCounter;
	TInt iOverflowCounter;
	
	TUint iCurrentOp;
	TInt iNumFiles;
	TUint16 iOption;

	RArray<TEntry> iEntries;
	RArray<TFileName> iRecords;	// this is the output we produce
	
	CTimerLogger* iLogger;
	
	CFsNotify* iNotify;
	  
	TMdsFSPStatusPckg iPluginStatusPkg;
    CMdsPluginControl iPlugin;	
	
	RFs iFs;
	};

// An AO aims for stopping the Active Scheduler when test finish
class CTestStopper : public CActive
	{
	
public:
	CTestStopper();
	~CTestStopper();
	
	void DoCancel();
	void RunL();
	
	void StartWaitingForFile();
	
private:
	TFileName iTestEndFile;
	RFs iFs;
	};

#include "t_notify_perf.inl"