kerneltest/f32test/bench/t_fat_perf_impl.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/bench/t_fat_perf_impl.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,811 @@
+// 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--*/