kerneltest/f32test/bench/t_fat_perf_impl.cpp
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) 1996-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:
// File Name:		f32test/bench/t_fat_perf_impl.cpp
// This file contains FRAMEWORK implementation for the tests to test
// the FAT Performance on large number of files (PREQ 1885).
// 
//

// Include Files
#include "t_fat_perf.h"
#include <e32math.h>
#include <hal.h>

const TInt gMeasurementScale = K1mSec;	// defines the scales of measurement 

CMeasureAndLogUnit::CMeasureAndLogUnit()
	{
     
	}

void CMeasureAndLogUnit::ConstructL(const TMLUnitParam& aParam)
	{
	iID = aParam.iID;
	User::LeaveIfError(HAL::Get(HALData::EFastCounterFrequency, iFreq));
	iScale = gMeasurementScale;
	iLogItemNo = 1;
	}

CMeasureAndLogUnit* CMeasureAndLogUnit::NewLC(const TMLUnitParam& aParam)
	{
	CMeasureAndLogUnit* self = new(ELeave) CMeasureAndLogUnit();
	CleanupStack::PushL(self);
	self->ConstructL(aParam);
	return self;
	}

CMeasureAndLogUnit* CMeasureAndLogUnit::NewL(const TMLUnitParam& aParam)
	{
	CMeasureAndLogUnit* self = CMeasureAndLogUnit::NewLC(aParam);
	CleanupStack::Pop(self);
	return self;
	}

CMeasureAndLogUnit::~CMeasureAndLogUnit()
	{

	}

TInt CMeasureAndLogUnit::MeasureStart()
	{
	iStartStatus = User::FastCounter();
	return KErrNone;
	}
TInt CMeasureAndLogUnit::MeasureEnd()
	{
	iEndStatus = User::FastCounter();
	return KErrNone;
	}

//Measurement and Log unit
TInt CMeasureAndLogUnit::Log(const TFileName& aDirName, const TFileName& aFileName, TUint aCurrentFileNo, TUint aCurrentFilePos)
	{
	TReal measure = iScale * ((TReal)(iEndStatus - iStartStatus)) / ((TReal) iFreq);
	TBuf<0x10> scale;
	if (iScale == K1mSec)  
		{
		scale = _L("millisecond");
		}
	else if (iScale == K1Sec) 
		{
		scale = _L("second");
		}
	else if (iScale == K1uSec) 
		{
		scale = _L("microsecond");
		}
	test.Printf(_L("[LOG]: \t%u \t\"%S\" \t%f \t%S \t\"%S\" \t%u \t%u\n"), 
					iLogItemNo, &aDirName, measure, &scale, &aFileName, aCurrentFileNo, aCurrentFilePos);

	iLogItemNo++;

	return KErrNone;
	}



CFileOperationUnit::CFileOperationUnit()
:iDirCreated(EFalse)
	{

	}

// File Operation Unit
void CFileOperationUnit::ConstructL(const TFileOpUnitParam& aParam)
	{
	iDirName = aParam.iDirName;
	iNamingSchemeParam = aParam.iNamingSchemeParam;
	iFileOpMode = aParam.iFileOpMode;
	iMLUnitPtr = aParam.iMLUnitPtr;

	TInt rel = iRFs.Connect();
	if (rel != KErrNone)
		{
		test.Printf(_L("<<Error>>: DIRUNIT: iRFs.Connect = %d\n"), rel);
		test(EFalse);
		}
	}


CFileOperationUnit* CFileOperationUnit::NewLC(const TFileOpUnitParam& aParam)
	{
	CFileOperationUnit* self = new(ELeave) CFileOperationUnit();
	CleanupStack::PushL(self);
	self->ConstructL(aParam);
	return self;
	}

CFileOperationUnit* CFileOperationUnit::NewL(const TFileOpUnitParam& aParam)
	{
	CFileOperationUnit* self = CFileOperationUnit::NewLC(aParam);
	CleanupStack::Pop(self);
	return self;
    }

CFileOperationUnit::~CFileOperationUnit()
	{
	iRFs.Close();
	}

void CFileOperationUnit::SetMLUnit(CMeasureAndLogUnit* aMLUnit)
	{
	iMLUnitPtr = aMLUnit;
	}


// File Operation unit - Test Functions 
TInt CFileOperationUnit::Run(const TFileName& aDirName, const TFileName& aFileName, TBool aIsTakingMeasurement, TUint aCurFileNo, TUint aCurFilePos)
	{
	TMLParam mlParam;
	RFile	rfile;
	TInt	rel = KErrNone;
	TInt	rel1 = KErrNone; 
	TInt	bufMaxLength = 4096;
	TInt	Ret1 = KErrNone; 
	TInt	Ret2 = KErrNone; 
	RBuf8 	buf; 
	RBuf8	databuf;

		
	if (aIsTakingMeasurement && iMLUnitPtr != NULL)
		{
		mlParam.iDirName = iDirName;
		mlParam.iFileName = aFileName;
		mlParam.iNamingScheme = iNamingSchemeParam;
		mlParam.iCurFileNo = aCurFileNo;
		mlParam.iFileOpMode = iFileOpMode;
		}
	else if (aIsTakingMeasurement && iMLUnitPtr == NULL)
		{
		test.Printf(_L("<<Error>>CZFileOperationUnit::Run(): no logging unit associated!!\n"));
		return KErrGeneral;
		}

	switch (iFileOpMode)
		{
		case EFATPerfFileReplace:		// Replace Operations
			{
			test.Printf(_L("CZFileOperationUnit::Run(): EZFileReplace\n"));
			break;
			}
		case EFATPerfFileCreate:
			{
			if (!iDirCreated && gTestCase != EFATPerfCreate)  // 'EFATPerfCreate' is  an enum defined in header file t_fat_perf.h
				{
				rel = iRFs.MkDirAll(aFileName);
				test.Printf(_L("MakeDirAll \"%S\" error: %d\n"), &aFileName, rel);					
				if (rel != KErrNone && rel != KErrAlreadyExists)
					{
					test.Printf(_L("<<Error>>: MakeDirAll \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
				iDirCreated = ETrue;
				}
			if (aIsTakingMeasurement)
				{
				iMLUnitPtr->MeasureStart();
				rel = rfile.Create(iRFs, aFileName, EFileShareAny);
				iMLUnitPtr->MeasureEnd();
				iMLUnitPtr->Log(aDirName, aFileName, aCurFileNo, aCurFilePos);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileCreating \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
				}
			else
				{
				rel = rfile.Create(iRFs, aFileName, EFileShareAny);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileCreating error: %d\n"), rel);
					return rel;
					}
				}
			break;
			}
	
		case EFATPerfFileOpen:      // Open Operations
			{
			if (aIsTakingMeasurement)
				{
				iMLUnitPtr->MeasureStart();
				rel = rfile.Open(iRFs, aFileName, EFileShareAny);
				iMLUnitPtr->MeasureEnd();
				iMLUnitPtr->Log(aDirName, aFileName, aCurFileNo, aCurFilePos);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileOpen \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
				}
			else
				{
				rel = rfile.Open(iRFs, aFileName, EFileShareAny);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileOpen error: %d\n"), rel);
					return rel;
					}
				}
			break;
			}
		
	
		case EFATPerfFileDelete:     // Delete Operations
			{
			
		
			if (aIsTakingMeasurement)
				{
				iMLUnitPtr->MeasureStart();
				rel = iRFs.Delete(aFileName);
				iMLUnitPtr->MeasureEnd();
				iMLUnitPtr->Log(aDirName, aFileName, aCurFileNo, aCurFilePos);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileDelete \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
															
				}
			else
				{
			
				rel = rfile.Open(iRFs, aFileName, EFileShareAny);
				if (rel != KErrNone)
				{
					test.Printf(_L("<<Error>>: FileOpen \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
				rfile.Close(); // file needs be closed before  deleting.
				
				rel = iRFs.Delete(aFileName);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileDelete \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
						
				}
			break;
			}
		
			
			
		case EFATPerfFileWrite:			//Write Operations
			{
			
			// creating buffer for Write operation 
			Ret2 = databuf.CreateMax(bufMaxLength);
	
			if (Ret2 != KErrNone)
				{
				test.Printf(_L("<<Error>>: Unable to create a buffer 'databuf': %d\n"), Ret2);
				return Ret2;
				}
			
			databuf.Fill('A', bufMaxLength);	
	
					
			if (aIsTakingMeasurement)
				{
				
				rel = rfile.Open(iRFs, aFileName, EFileShareAny|EFileWrite);
				iMLUnitPtr->MeasureStart();
				rel1 = rfile.Write(databuf);
				iMLUnitPtr->MeasureEnd();
				iMLUnitPtr->Log(aDirName, aFileName, aCurFileNo, aCurFilePos);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileOpen \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
			
				if (rel1 != KErrNone)
				{
				test.Printf(_L("<<Error>>: FileWrite \"%S\" error: %d\n"), &aFileName, rel1);
				return rel1;
				}
								
				}
			else
				{
			
				rel = rfile.Open(iRFs, aFileName, EFileShareAny|EFileWrite);
				rel1 = rfile.Write(databuf);
				
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileOpen error: %d\n"), rel);
					return rel;
					}
				
				if (rel1 != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileWrite error: %d\n"), rel1);
					return rel1;
					}
				}
			break;
			}
		
		
		
		case EFATPerfFileRead:			// Read Operations
			{
			
			// creating the buffer for Read operation 
			Ret1 = buf.CreateMax(bufMaxLength);	
			if (Ret1 != KErrNone)
				{
				test.Printf(_L("<<Error>>: Unable to create a buffer 'buf': %d\n"), Ret1);
				return Ret1;
				}
			
		
			if (aIsTakingMeasurement)
				{
				
				rel = rfile.Open(iRFs, aFileName, EFileShareAny|EFileRead);
				iMLUnitPtr->MeasureStart();
				rel1 = rfile.Read(buf);
				iMLUnitPtr->MeasureEnd();
				iMLUnitPtr->Log(aDirName, aFileName, aCurFileNo, aCurFilePos);
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileOpen \"%S\" error: %d\n"), &aFileName, rel);
					return rel;
					}
				if (rel1 != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileRead \"%S\" error: %d\n"), &aFileName, rel1);
					return rel1;
					}
				}
			else
				{
				rel = rfile.Open(iRFs, aFileName, EFileShareAny|EFileRead);
				rel1 = rfile.Read(buf);
				
				if (rel != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileOpen error: %d\n"), rel);
					return rel;
					}
				
				if (rel1 != KErrNone)
					{
					test.Printf(_L("<<Error>>: FileRead \"%S\" error: %d\n"), &aFileName, rel1);
					return rel1;
					}
			 	}
			break;
			}
		
		default:
			{
			// Error: KErrNotSupported!!
			test.Printf(_L("<<Error>>CZFileOperationUnit::Run(): KErrNotSupported!!\n"));
			return KErrNotSupported;
			}
		 }

	rfile.Close();
	buf.Close(); 
	databuf.Close();
	return KErrNone;
	}



CDirUnit::CDirUnit()
	{

	}

void CDirUnit::ConstructL(const TDirUnitParam& aParam, const TChar aDriveChar)
	{
	iPriority = aParam.iPriority;
	iDirName.Copy(aParam.iDirName);
	iDirName[0] = (TUint16)aDriveChar;  
	iRuns = aParam.iRuns;
	iCurrentRunNo = 1;
	iFilesPerRun = aParam.iFilesPerRun;
	iCurrentFileNo = 1;
	iTotalFileNo = iRuns * iFilesPerRun;
	iSampleInterval = aParam.iSampleInterval;
	
	
	iConOrRan = aParam.iNamingScheme.iConOrRan;
	iUniOrAsc = aParam.iNamingScheme.iUniOrAsc;
	iZeroPadFileNumberForFixedLengthFileNames = aParam.iNamingScheme.iZeroPadFileNumber;
	iFileNameBase = aParam.iNamingScheme.iFileNameBase;
	iMaxFileNameLength = aParam.iNamingScheme.iMaxFileNameLength;
	iMinStringLength = aParam.iNamingScheme.iMinStringLength;

	if (iZeroPadFileNumberForFixedLengthFileNames)
	    {
	    // Calculate how many digits the highest file postfix will have so that
	    // zero padding can be added.
	    TFileName fileNamePostFixBuffer;
	    fileNamePostFixBuffer.AppendNum(iTotalFileNo);
	    iNumDigitsInTotalFileNo = fileNamePostFixBuffer.Length();
	    }
	else
	    {
	    iNumDigitsInTotalFileNo = 0;
	    }
	
	TFileOpUnitParam fileOpParam;
	fileOpParam.iDirName = iDirName;
	fileOpParam.iNamingSchemeParam = aParam.iNamingScheme;
	fileOpParam.iFileOpMode = aParam.iFileOpMode;
	fileOpParam.iMLUnitPtr = iMLUnitPtr;
	CFileOperationUnit* fileOpUnit = CFileOperationUnit::NewL(fileOpParam);
	iFileOpUnit = fileOpUnit;
	}

CDirUnit* CDirUnit::NewLC(const TDirUnitParam& aParam, const TChar aDriveChar)
	{
	CDirUnit* self = new(ELeave) CDirUnit();
	CleanupStack::PushL(self);
	self->ConstructL(aParam, aDriveChar);
	return self;
	}

CDirUnit* CDirUnit::NewL(const TDirUnitParam& aParam, const TChar aDriveChar)
	{
	CDirUnit* self = CDirUnit::NewLC(aParam, aDriveChar);
	CleanupStack::Pop(self);
	return self;
	}

CDirUnit::~CDirUnit()
	{
	delete iFileOpUnit;
	}

TInt CDirUnit::Priority()
	{
	return iPriority;
	}

const TFileName&	CDirUnit::Name()
	{
	return iDirName;
	}


_LIT(KFileExtDefault,	".TXT");

//Character set for random file generation
static TText16 gFileNameCharPool[] =
	{
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
//	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',	
	'-', '_', '^', '$', '~', '!', '#', '%', '&', '{', '}', '@', '(', ')', '\'',
	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
	};

const TUint KNumOfLegalAsciiChar = 51;


// Random String Generation for file names
TFileName CDirUnit::GenerateRandomString(const TUint aMinStringLength, const TUint aMaxStringLength, const TNamingUniOrAsc aUniOrAsc)
	{
	TInt strLen = -1;
	TFileName aFileName;
	
	if (aMinStringLength == aMaxStringLength && aMaxStringLength != 0)
		{
		strLen = aMinStringLength;
		}
	else if (aMaxStringLength > aMinStringLength)
		{
		do
			{
			strLen = aMinStringLength + ((TUint) (Math::Random())) % (aMaxStringLength - aMinStringLength);
			}
		while (strLen == 0);
		}
	else
		{
		test.Printf(_L("<<Random String Error>>: Bad String Length Setting!!\n"));
		}
	
	if (aUniOrAsc == EAscii)
		{
		TInt i;
		for (i = 0; i < strLen; ++i)
			{
			TInt nextCharIdx = (((TUint) (Math::Random())) % KNumOfLegalAsciiChar);
			aFileName.Append((TChar)gFileNameCharPool[nextCharIdx]);
			}
		}
	else if(aUniOrAsc == EUnicode)
		{
		test.Printf(_L("<<Random String Error>>: Unicode is not supported yet!!\n"));
		}
    else 
        {
        test(0);
        }

	return aFileName;
	}

TBool CDirUnit::FileNameIsUnique(const TFileName& /*aFileName*/)
	{

	return ETrue;

	}

// File Name Generation
TInt CDirUnit::GenerateFileName(TFileName& aFileName)
	{
	TBool fileNameIsUnique = EFalse;
	if (iRuns == iFilesPerRun && iFilesPerRun == 1)
		{
		aFileName.Zero();
		aFileName.Append(iDirName);
		aFileName.Append(iFileNameBase);
		aFileName.Append(KFileExtDefault);
		fileNameIsUnique = FileNameIsUnique(aFileName);
		if (fileNameIsUnique == EFalse)
			{
			test.Printf(_L("<<Error>>: File name is not unique!\n"));
			return KErrArgument;
			}
		return KErrNone;
		}
	
	if (iConOrRan == EConsecutive)
		{
		aFileName.Zero();
		aFileName.Append(iDirName);
		aFileName.Append(iFileNameBase);
		
		if (iZeroPadFileNumberForFixedLengthFileNames)
		    {
		    aFileName.AppendNumFixedWidth(iCurrentFileNo, EDecimal, iNumDigitsInTotalFileNo);
		    }
		else
		    {
		    aFileName.AppendNum(iCurrentFileNo);
		    }

		aFileName.Append(KFileExtDefault);
		fileNameIsUnique = FileNameIsUnique(aFileName);
		if (fileNameIsUnique == EFalse)
			{
			test.Printf(_L("<<Error>>: File name is not unique!\n"));
			return KErrArgument;
			}
		return KErrNone;
		}
	else if(iConOrRan == ERandom)
		{
		if (iMaxFileNameLength <= 0)
			{
			test.Printf(_L("<<Parameter Error>>: DIR: \"%S\"\n"), &iDirName);
			test.Printf(_L("<<Parameter Error>>: EZRandom && iMaxNameLength <= 0\n"));
			return KErrArgument;
			}

		do
			{
			aFileName.Zero();
			aFileName.Append(iDirName);
			aFileName.Append(iFileNameBase);
			TFileName randomString = GenerateRandomString(iMinStringLength, iMaxFileNameLength, iUniOrAsc);
			aFileName.Append(randomString);
			aFileName.Append(KFileExtDefault);
			fileNameIsUnique = FileNameIsUnique(aFileName);
			}
		while(fileNameIsUnique == EFalse);
		
		return KErrNone;
		}

	return KErrNone;
	}

void CDirUnit::SetMLUnit(CMeasureAndLogUnit* aMLUnitPtr)
	{
	iMLUnitPtr = aMLUnitPtr;
	iFileOpUnit->SetMLUnit(aMLUnitPtr);
	}

TBool CDirUnit::CheckMeasurementTaking()
	{
	
	return (iSampleInterval > 0 && 
			iCurrentFileNo >= iSampleInterval && 
			((iCurrentFileNo % iSampleInterval) == 0));
	}

TInt CDirUnit::Run(const TInt aCurrentPriority)
	{
	if (aCurrentPriority != iPriority)
		{
		return KErrNotReady;
		}


	if (iCurrentRunNo <= iRuns)
		{
		
		TUint i;
		for (i = 0; i < iFilesPerRun; ++i, ++iCurrentFileNo)
			{
			// check currentFileNo < totalFileNo
			if (iCurrentFileNo > iTotalFileNo)
				{
				// Error
				User::Panic(_L("<<CZDirUnit::Run>>: file overflow!"), 100);
				}
			// generate file name
			TFileName fileName;
			GenerateFileName(fileName);
			
			// check if is taking measurement
			TBool isTakingMeasurement = CheckMeasurementTaking();

			// file operation
			iFileOpUnit->Run(iDirName, fileName, isTakingMeasurement, iCurrentFileNo, iCurrentFileNo);
			}
		iCurrentRunNo++;
		}

	if (iCurrentRunNo > iRuns)
		{
		return KErrCompletion;
		}
	return KErrNone;
	}



CExecutionUnit::CExecutionUnit()
	{

	}

void CExecutionUnit::ConstructL(CMeasureAndLogUnit* aMLUnitPtr, const TChar aDriveChar)
	{
	iCurPriority = -1;
	iDriveChar = aDriveChar;

	if (aMLUnitPtr != NULL)
		{
		iMLUnitPtr = aMLUnitPtr;
		}
	}

CExecutionUnit* CExecutionUnit::NewLC(CMeasureAndLogUnit* aMLUnitPtr, const TChar aDriveChar)
	{
	CExecutionUnit* self = new(ELeave) CExecutionUnit();
	CleanupStack::PushL(self);
	self->ConstructL(aMLUnitPtr, aDriveChar);
	return self;
	}

CExecutionUnit* CExecutionUnit::NewL(CMeasureAndLogUnit* aMLUnitPtr, const TChar aDriveChar)
	{
	CExecutionUnit* self = CExecutionUnit::NewLC(aMLUnitPtr, aDriveChar);
	CleanupStack::Pop(self);
	return self;
	}

CExecutionUnit::~CExecutionUnit()
	{
	TInt count = iDirUnitArray.Count();
	if (count > 0)
		{
		TInt i;
		for (i = 0; i < count; ++i)
			{
			CDirUnit* tempDirUnit = iDirUnitArray[i];
			delete tempDirUnit;
			}
		}
	iDirUnitArray.Close();
	}


TInt CExecutionUnit::AddDirUnitL(const TDirUnitParam& aParam)
	{
	CDirUnit* dirUnit = CDirUnit::NewL(aParam, iDriveChar);
	if (iMLUnitPtr)
		{
		dirUnit->SetMLUnit(iMLUnitPtr);
		}
	TInt rel = iDirUnitArray.Append(dirUnit);
	return rel;
	}


// To Re-calculate the priority
TInt CExecutionUnit::RecalculateCurrentPrioirty()
	{
	// findout the least number of iPriority in current array
	if (iDirUnitArray.Count() == 0)
		{
		iCurPriority = -1;
		return iCurPriority;
		}

	TBool found = EFalse;

	TInt i;
	
	for (i = 0; i < iDirUnitArray.Count(); ++i)
		{
		if (iDirUnitArray[i]->Priority() == iCurPriority)
			{
			found = ETrue;
			}
		}
	
	if (!found)
		{
		iCurPriority = iDirUnitArray[0]->Priority();
		for (i = 0; i < iDirUnitArray.Count(); ++i)
			{
			if (iDirUnitArray[i]->Priority() < iCurPriority)
				{
				iCurPriority = iDirUnitArray[i]->Priority();
				}
			}
		}

	return iCurPriority;
	}

TInt  CExecutionUnit::Run()
	{
	test.Printf(_L("CZExecutionUnit::Run()\n"));
	
	TInt curPriority = RecalculateCurrentPrioirty();
	
	while (iDirUnitArray.Count() > 0)
		{
		TInt i;
		for (i = 0; i < iDirUnitArray.Count(); ++i)
			{
			TInt rel = iDirUnitArray[i]->Run(curPriority);
			if (rel == KErrCompletion)
				{
				test.Printf(_L("DIR: \"%S\" terminated.\n"), &iDirUnitArray[i]->Name());
				CDirUnit* dirUnit = iDirUnitArray[i];
				iDirUnitArray.Remove(i);
				delete dirUnit;
				--i;
				curPriority = RecalculateCurrentPrioirty();
				}
			else if (rel == KErrNotReady)
				{
				// do nothing
            	}
			}
		}

	test.Printf(_L("\n"));
	test.Printf(_L("CZExecutionUnit::Finished.\n"));
	return KErrNone;
	}

/*-- EOF--*/