smartinstaller/adm/src/ADMPackageInfo.cpp
branchADM
changeset 48 364021cecc90
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smartinstaller/adm/src/ADMPackageInfo.cpp	Wed Jun 30 11:01:26 2010 +0530
@@ -0,0 +1,809 @@
+/*
+* Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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: 
+*     CPackageInfo implementation
+*
+*
+*/
+
+
+#include <e32base.h>
+#include <f32file.h>
+#include <sysutil.h>        // SysUtil::DiskSpaceBelowCriticalLevel()
+
+#include "ADMXmlParser.h"
+#include "ADMPackageInfo.h"
+#include "ADMDownloadHandler.h"
+#include "ADMAppUi.h"
+
+#include "macros.h"
+
+//TODO: Right place?!
+// The extension of the changes file
+_LIT(KChangesExt,"_changes.xml");
+
+CPackageInfo* CPackageInfo::NewLC()
+	{
+	CPackageInfo* object = new ( ELeave ) CPackageInfo();
+	CleanupStack::PushL( object );
+	object->ConstructL();
+	return object;
+	}
+
+CPackageInfo* CPackageInfo::NewL()
+	{
+	CPackageInfo* object = CPackageInfo::NewLC();
+	CleanupStack::Pop();
+	return object;
+	}
+
+void CPackageInfo::ConstructL()
+	{
+	}
+
+CPackageInfo::CPackageInfo() :
+	iPackageStatus(EPackageStatusUnknown),
+	iEdgeDlinkHdr(_FOFF(Edge, iEdgeDlink)),
+	iEdgeDlinkIter(iEdgeDlinkHdr)
+	{
+	}
+
+CPackageInfo::~CPackageInfo()
+	{
+	Edge* currentitem;
+
+	iEdgeDlinkIter.SetToFirst();
+
+	// Clear the memory allocated for all Edges.
+	while((currentitem = iEdgeDlinkIter++) != NULL)
+		{
+		currentitem->iEdgeDlink.Deque();
+		delete currentitem;
+		};
+
+	DELETE_IF_NONNULL( iPackageName );
+	DELETE_IF_NONNULL( iVendor );
+	DELETE_IF_NONNULL( iDateOfSubmission );
+	DELETE_IF_NONNULL( iDateOfModification );
+	DELETE_IF_NONNULL( iUrl );
+	DELETE_IF_NONNULL( iDownloadUrl );
+	DELETE_IF_NONNULL( iDepFileName );
+	DELETE_IF_NONNULL( iChangesFileName );
+	DELETE_IF_NONNULL( iSisPackageName );
+	}
+
+void CPackageInfo::AddEdgeL(CPackageInfo* aDest)
+	{
+	User::LeaveIfNull(aDest);
+
+	Edge* newEdge = Edge::NewL(this, aDest);
+	if (iEdgeDlinkHdr.IsEmpty())
+		{
+		// This is the first Edge in the list
+		iEdgeDlinkHdr.AddFirst(*newEdge);
+		iEdgeDlinkIter.SetToFirst();
+		}
+	else
+		{
+		// Append Edge to the list
+		iEdgeDlinkHdr.AddLast(*newEdge);
+		iEdgeDlinkIter.SetToLast();
+		}
+	}
+
+void CPackageInfo::VisitL(CDepTree *aDepTree)
+	{
+	// TODO: Proper error handling
+	User::LeaveIfNull(aDepTree);
+
+	Edge *e;
+	CPackageInfo *temp;
+
+	if (iVisited == BEING_VISITED)
+		{
+		// Cycle is detected
+		aDepTree->iCyclePresent = ETrue;
+		return;
+		}
+	if (iVisited == DONE_VISITED)
+		{
+		// Node already visited added to the fetch list
+		return;
+		}
+
+	iVisited = BEING_VISITED;
+
+	// Visit all the Edges first
+	while(iEdgeDlinkIter!= NULL)
+		{
+		e = iEdgeDlinkIter--;
+		temp = e->GetVertexDst();
+		temp->VisitL(aDepTree);
+		}
+	iVisited = DONE_VISITED;
+
+	aDepTree->AddFetchPackageInfo(this);
+	}
+
+void CPackageInfo::SetDepFileNameL(const TDesC& aName)
+	{
+	__ASSERT_ALWAYS( aName.Length() > 0, User::Leave( KErrArgument) );
+
+	DELETE_IF_NONNULL( iDepFileName );
+	iDepFileName = aName.AllocL();
+	}
+
+//TODO : Clean possible?
+void CPackageInfo::SetChangesFileNameL()
+	{
+	DELETE_IF_NONNULL( iChangesFileName );
+
+#ifdef FEATURE_CHANGES_USE_UID
+	//By default, use Packageuid as the Changes filename.
+	//set the length as ( PackageUIDLength (8) + Changes_ext length )
+	iChangesFileName = HBufC::NewL(8 + KChangesExt().Length());
+	TPtr nameBufPtr = iChangesFileName->Des();
+	nameBufPtr.Num(GetPackageUid(), EHex);
+	nameBufPtr.Append(KChangesExt);
+#else
+	//Use Packagename as the Changes filename.
+	// If package name is NULL, then Package UID is used as Changes file name.
+	if( GetPackageName() != NULL )
+		{
+		iChangesFileName = HBufC::NewL( GetPackageName()->Length() +
+										KChangesExt().Length() );
+		TPtr nameBufPtr = iChangesFileName->Des();
+		nameBufPtr.Copy(GetPackageName()->Des());
+
+		const TInt nameLength = GetPackageName()->LocateReverse('.');
+
+		if (nameLength != KErrNotFound)
+			{
+			//Remove the extension.
+			nameBufPtr.Delete( nameLength, GetPackageName()->Length() - nameLength);
+			}
+		nameBufPtr.Append(KChangesExt);
+		}
+	else
+		{
+		iChangesFileName = HBufC::NewL(8 + KChangesExt().Length());
+		TPtr nameBufPtr = iChangesFileName->Des();
+		nameBufPtr.Num(GetPackageUid(), EHex);
+		nameBufPtr.Append(KChangesExt);
+		}
+#endif
+	}
+
+void CPackageInfo::SetSisFileNameL(const TDesC& aName)
+	{
+	__ASSERT_ALWAYS( aName.Length() > 0, User::Leave( KErrArgument) );
+
+	DELETE_IF_NONNULL( iSisPackageName );
+	iSisPackageName = aName.AllocL();
+	}
+
+// -----------------------------------------------------------------------------
+// Creates download URL for the package. The constructed URL is stored in
+// member variable iDownloadUrl. The URL is constructed only once, the
+// subsequent calls to this return iDownloadUrl.
+//
+//     base_url/package/version/dep_file
+// i.e.
+//     http://server.somewhere.net/root/qt/4.6.1/qt_dep.xml
+// -----------------------------------------------------------------------------
+//
+HBufC8* CPackageInfo::GetDownloadUrlL()
+	{
+#ifdef FEATURE_CHANGES_DOWNLOAD_URL
+	if (iDownloadUrl)
+		{
+		return iDownloadUrl;
+		}
+
+	// Url should never be null as specifying
+	// the Url in changes file is mandatory
+	User::LeaveIfNull(iUrl);
+
+	TInt len = iUrl->Des().Length();
+#ifdef FEATURE_CHANGES_USE_UID
+	len += 8; // UID length as HEX string // iPackageName->Length();
+#else
+	len += iPackageName->Length();
+#endif
+
+	// TVersion: iMajor(8bit), iMinor(8bit), iBuild(16bit) = 255 255 65535
+	// delimiters: /qt/4.6.1/ => //../ = (len=5)
+	len += (3+3+5 + 5);
+
+	HBufC8* url = HBufC8::NewL(len);
+	TPtr8 urlPtr = url->Des();
+	// Construct the download path:
+	//     base_url/package/version/dep_file
+	// i.e.
+	//     http://server.somewhere.net/root/qt/4.6.1/qt_dep.xml
+	urlPtr.Copy(*iUrl);
+
+	// Append forward slash if that's missing
+	if (urlPtr.Right(1)[0] != '/')
+		{
+		urlPtr.Append('/');
+		}
+
+#ifdef FEATURE_CHANGES_USE_UID
+	urlPtr.AppendNum(iPackageUid, EHex);
+#else
+	urlPtr.Append(iPackageName->Des());
+#endif
+	urlPtr.Append('/');
+	urlPtr.AppendNum(iVersion.iMajor);
+	urlPtr.Append('.');
+	urlPtr.AppendNum(iVersion.iMinor);
+	urlPtr.Append('.');
+	urlPtr.AppendNum(iVersion.iBuild);
+	urlPtr.Append('/');
+
+	iDownloadUrl = url;
+
+	return url;
+#else
+	// Url should never be null as specifying
+	// the Url in changes file is mandatory
+	User::LeaveIfNull(iUrl);
+	return iUrl;
+#endif // FEATURE_CHANGES_DOWNLOAD_URL
+	}
+
+#ifdef USE_LOGFILE
+CDepTree* CDepTree::NewLC(RFileLogger& aLogger, const TDesC& aDownloadPath)
+	{
+	CDepTree* object = new ( ELeave ) CDepTree(aLogger);
+#else
+CDepTree* CDepTree::NewLC(const TDesC& aDownloadPath)
+	{
+	CDepTree* object = new ( ELeave ) CDepTree();
+#endif
+	CleanupStack::PushL( object );
+	object->ConstructL(aDownloadPath);
+	return object;
+	}
+
+#ifdef USE_LOGFILE
+CDepTree* CDepTree::NewL(RFileLogger& aLogger, const TDesC& aDownloadPath)
+	{
+	CDepTree* object = CDepTree::NewLC(aLogger, aDownloadPath);
+#else
+CDepTree* CDepTree::NewL(const TDesC& aDownloadPath)
+	{
+	CDepTree* object = CDepTree::NewLC(aDownloadPath);
+#endif
+	CleanupStack::Pop();
+	return object;
+	}
+
+#ifdef USE_LOGFILE
+CDepTree::CDepTree(RFileLogger& aLogger) :
+	iLog(aLogger),
+#else
+CDepTree::CDepTree() :
+#endif
+	iCurrentPackage(-1),
+	iSortedPackage(-1),
+	iCyclePresent(EFalse),
+	iPackageDlinkHdr(_FOFF(CPackageInfo,iPackageDlink)),
+	iPackageDlinkFetchIter(iPackageDlinkHdr)
+	{
+	iFetchList.Reset();
+	iSortedList.Reset();
+	}
+
+void CDepTree::ConstructL(const TDesC& aDownloadPath)
+	{
+	iDownloadPath = aDownloadPath.AllocL();
+	}
+
+CDepTree::~CDepTree()
+	{
+	DELETE_IF_NONNULL( iDownloadPath );
+
+	CPackageInfo* currentPackage;
+	iPackageDlinkFetchIter.SetToFirst();
+
+	TDblQueIter<CPackageInfo> PackageIter(iPackageDlinkHdr);
+	PackageIter.SetToFirst();
+
+	// Clear memory allocated for all packages
+	while((currentPackage = PackageIter++) != NULL)
+		{
+		currentPackage->iPackageDlink.Deque();
+		delete currentPackage;
+		};
+
+	iFetchList.Close();
+	iSortedList.Close();
+	}
+
+const TLinearOrder<CPackageInfo> CPackageInfo::KSortOrderByDrivePriority(CPackageInfo::CompareByDrivePriority);
+
+TInt CPackageInfo::CompareByDrivePriority( const CPackageInfo& aPackageOne, const CPackageInfo& aPackageTwo )
+{
+	if ( (aPackageOne.GetDrivePriority()) > (aPackageTwo.GetDrivePriority()) )
+		{
+		return -1;
+		}
+	else
+		{
+		return 1;
+		}
+}
+
+TBool CDepTree::ConstructFetchListL()
+	{
+	if(iPackageDlinkHdr.IsEmpty())
+		{
+		return EFalse;
+		}
+
+	CPackageInfo *rootNode = iPackageDlinkHdr.First();
+	rootNode->VisitL(this);
+	return ETrue;
+	}
+
+TBool CDepTree::SetDriveInfo()
+	{
+#ifdef FEATURE_INSTALL_DRIVE_SELECTION
+	TInt driveIndex = 0;
+	CPackageInfo* currentNode = NULL;
+	TBool retStatus = ETrue; // Default to successful check
+	RArray<TChar> driveLetters(EDriveZ-EDriveA+1);
+	RArray<TInt64> driveSpaces(EDriveZ-EDriveA+1);
+	RFs fs;
+
+	if (fs.Connect() != KErrNone)
+		{
+		return EFalse;
+		}
+
+	CleanupClosePushL(fs);
+	CleanupClosePushL(driveLetters);
+	CleanupClosePushL(driveSpaces);
+
+	// Get the drive letters and spaces
+	TRAPD(err, GetDriveListL(fs, driveLetters, driveSpaces) );
+	if (err != KErrNone)
+		{
+		return EFalse;
+		}
+
+	// The packages are sorted based on priority
+	for (TInt index = 0; (index < iSortedList.Count()) && (retStatus != EFalse); index++ )
+		{
+		//LOG2( "Index is %d", index );
+
+		currentNode = iSortedList[index];
+
+		const TChar mandatoryDriveLetter = currentNode->GetMandatoryInstallDrive();
+
+		if ( mandatoryDriveLetter )
+			{
+			// Reset the driveIndex for drive selection of each package.
+			for ( driveIndex = 0; driveIndex < driveSpaces.Count(); driveIndex++ )
+				{
+				// Check whether the current drive is the mandatory drive.
+				if ( driveLetters[driveIndex] == mandatoryDriveLetter )
+					{
+					// Check whether there is enough space in mandatory drive.
+					if ( currentNode->GetInstallSize() < driveSpaces[driveIndex] )
+						{
+						LOG3( "PkgUid 0x%08X installation forced to %c:", currentNode->GetPackageUid(), (char)driveLetters[driveIndex] );
+						currentNode->SetInstallDrive(driveLetters[driveIndex]);
+						driveSpaces[driveIndex] -= currentNode->GetInstallSize();
+						}
+					else
+						{
+						retStatus = EFalse;
+						}
+					break;
+					}
+				}
+			}// if ( mandatoryDriveLetter )
+		else
+			{
+			// driveIndex is reset -> there could be a smaller package which fits in previous drive.
+			for ( driveIndex = 0; driveIndex < driveSpaces.Count(); driveIndex++ )
+				{
+				if (currentNode->GetInstallSize() < driveSpaces[driveIndex])
+					{
+					currentNode->SetInstallDrive(driveLetters[driveIndex]);
+					driveSpaces[driveIndex] -= currentNode->GetInstallSize();
+					break;
+					}
+				}
+			}// else of if ( mandatoryDriveLetter )
+
+		if ( driveSpaces.Count() <= driveIndex )
+			{
+			//Invalid mandatory drive specified.
+			retStatus = EFalse;
+			}
+		}// for loop of packages
+
+	// All the dependent sis files are assigned the drives where they need to be installed.
+	// Now go thru the drives to figure out which one can accommodate the download.
+
+	// This is done as a final act so that the memory is not blocked unnecessarily by download,
+	// which otherwise could be used to install a dependency sis.
+
+	// Reset the driveIndex -> start from system drive.
+	for ( driveIndex = 0; ( driveIndex < driveSpaces.Count() ) && ( retStatus != EFalse ); driveIndex++ )
+		{
+/*
+		TInt drive;
+		RFs::CharToDrive(driveLetters[driveIndex], drive);
+		if (!SysUtil::DiskSpaceBelowCriticalLevelL(&fs, iMaxDownloadSize, drive))
+			{
+*/
+		if ( driveSpaces[driveIndex] > iMaxDownloadSize )
+			{
+			driveSpaces[driveIndex] -= iMaxDownloadSize;
+			iDownloadDrive = driveLetters[driveIndex];
+			//Drive specified in download path is overriden.
+			iDownloadPath->Des()[0] = iDownloadDrive;
+			LOG4( "Download drive %c: free %ld (%.02f MB)", (char)iDownloadDrive, driveSpaces[driveIndex], (TReal)driveSpaces[driveIndex]/1048576.0 );
+			break;
+			}
+		}
+
+	// Fail, if no drive has space to max download size.
+	if ( driveSpaces.Count() <= driveIndex )
+		{
+		// Fail: no memory.
+		retStatus = EFalse;
+		}
+
+	CleanupStack::PopAndDestroy(3, &fs);
+
+	return retStatus;
+
+#else
+	TInt64 driveSpace = iMaxDownloadSize;
+	CPackageInfo* currentNode = NULL;
+	const TInt installDrive = RFs::GetSystemDrive();
+	TChar instDriveLetter;
+	TInt err;
+	TBool retStatus = ETrue; // Default to successful check
+	RFs fs;
+
+	err = fs.Connect();
+	if (err != KErrNone)
+		return EFalse;
+
+	CleanupClosePushL(fs);
+
+	RFs::DriveToChar(installDrive, instDriveLetter);
+
+	// The install size of all dependent packages to be installed is added to the required driveSpace.
+	for (TInt index = 0; index < iSortedList.Count(); index++ )
+		{
+		currentNode = iSortedList[index];
+		driveSpace += currentNode->GetInstallSize();
+		// Set the installation drive for the package
+		currentNode->SetInstallDrive(instDriveLetter);
+		}
+
+	// check whether there is enough space in C to download and install all dependencies.
+	TRAP( err, retStatus = !SysUtil::DiskSpaceBelowCriticalLevelL( &fs, driveSpace, installDrive ) );
+
+	// If free space check fails, indicate not enough space
+	if (err != KErrNone)
+		retStatus = EFalse;
+
+	CleanupStack::PopAndDestroy(&fs);
+
+	return retStatus;
+#endif
+	}
+
+void CDepTree::GetDriveListL(RFs& aRFs, RArray<TChar>& aDriveLetters, RArray<TInt64>& aDriveSpaces)
+	{
+	// This is the LFSS free space threshold
+	const TInt freeSpaceAdjustment = 1024 * 384;
+
+	// get information about drives
+	TDriveList driveList;
+
+	// List all drives in the system
+	User::LeaveIfError( aRFs.DriveList(driveList) );
+
+	TVolumeInfo volInfo;
+	TInt64 volSpace = 0;
+	TChar systemDriveLetter;
+	const TInt systemDrive = RFs::GetSystemDrive();
+
+	// Not sure whether the first DriveLetter in the while loop corresponds to SystemDrive.
+	// Hence setting it explicitly as the first entry in Drive Array
+	RFs::DriveToChar(systemDrive, systemDriveLetter);
+	if (aRFs.Volume(volInfo, systemDrive) == KErrNone)
+		{
+		LOG4( "SysDrive %c: Free %ld (%.02f MB)", (char)systemDriveLetter, volInfo.iFree, (TReal)volInfo.iFree/1048576.0 );
+		volSpace = volInfo.iFree - freeSpaceAdjustment;  // bytes
+		if (volSpace < 0)
+			{
+			volSpace = 0;
+			}
+		}
+
+	User::LeaveIfError(aDriveLetters.Append(systemDriveLetter));
+	User::LeaveIfError(aDriveSpaces.Append(volSpace));
+
+	// Check all drives
+	for (TInt driveNumber = EDriveA; driveNumber <= EDriveZ; driveNumber++)
+		{
+
+		if (!driveList[driveNumber])
+			{
+			// Not a recognised drive
+			continue;
+			}
+
+		if (aRFs.Volume(volInfo, driveNumber) != KErrNone)
+			{
+			// The volume is not usable (e.g. no media card inserted)
+			continue;
+			}
+
+		if (driveNumber == systemDrive)
+			{
+			//System Drive, already added to the list
+			continue;
+			}
+
+		if ( (volInfo.iDrive.iType==EMediaNotPresent) ||
+			 (volInfo.iDrive.iType==EMediaRom) ||
+			 (volInfo.iDrive.iType==EMediaRemote) ||
+			 (volInfo.iDrive.iType==EMediaRam) ||
+			 (volInfo.iDrive.iType==EMediaUnknown) )
+			{
+			// Exclude drives not suitable for installation
+			continue;
+			}
+
+		// Do not list read only and substituted drives as an option to install to
+		if (volInfo.iDrive.iDriveAtt & KDriveAttRom ||
+			volInfo.iDrive.iDriveAtt & KDriveAttSubsted)
+			{
+			continue;
+			}
+
+		const TInt64 volSpace = volInfo.iFree - freeSpaceAdjustment;  // bytes
+		if (volSpace < 0)
+			{
+			// Volume space below 0 => skip drive
+			continue;
+			}
+
+		TChar drvLetter;
+		User::LeaveIfError(RFs::DriveToChar(driveNumber, drvLetter));
+		User::LeaveIfError(aDriveLetters.Append(drvLetter));
+		User::LeaveIfError(aDriveSpaces.Append(volSpace));
+		LOG4( "Drive %c: Free %ld (%.02f MB)", (char)drvLetter, volSpace, (TReal)volSpace/1048576.0 );
+		} // for
+	}
+
+TBool CDepTree::IsDepTreeEmpty() const
+	{
+	return (iPackageDlinkHdr.IsEmpty());
+	}
+
+TBool CDepTree::IsCyclePresent() const
+	{
+	return iCyclePresent;
+	}
+
+void CDepTree::AddPackageInfo(CPackageInfo *aPackageInfo)
+	{
+	if(iPackageDlinkHdr.IsEmpty())
+		{
+		// This is the first node in the list
+		iPackageDlinkHdr.AddFirst(*aPackageInfo);
+		iPackageDlinkFetchIter.SetToFirst();
+		}
+	else
+		{
+		// Append node to the list
+		iPackageDlinkHdr.AddLast(*aPackageInfo);
+		}
+	}
+
+TPtrC CDepTree::GetDownloadPath() const
+	{
+	return iDownloadPath->Des();
+	}
+
+void CDepTree::AddFetchPackageInfo(CPackageInfo *aPackageInfo)
+	{
+	iFetchList.Append(aPackageInfo);
+	//Add the download/install sizes only if the package is not already installed.
+	if(aPackageInfo->iPackageStatus != EPackageInstalled)
+		{
+		iSortedList.InsertInOrder(aPackageInfo,CPackageInfo::KSortOrderByDrivePriority);
+		iTotalDownloadSize += aPackageInfo->iDownloadSize;
+
+		if(aPackageInfo->iDownloadSize > iMaxDownloadSize)
+			{
+			iMaxDownloadSize = aPackageInfo->iDownloadSize;
+			}
+		}
+	}
+
+CPackageInfo* CDepTree::LocatePackageInDepTree(const TUint32& aDepPackageUid)
+	{
+	CPackageInfo* currentItem;
+	TDblQueIter<CPackageInfo> PackageIter(iPackageDlinkHdr);
+	PackageIter.SetToFirst();
+
+	while((currentItem = PackageIter++) != NULL)
+		{
+		if(currentItem->iPackageUid == aDepPackageUid)
+			{
+			return currentItem;
+			}
+		};
+	return NULL;
+	}
+
+CPackageInfo* CDepTree::GetNextNode()
+	{
+	CPackageInfo* nextNode;
+
+	if(iPackageDlinkFetchIter++ != NULL)
+		{
+		// This is because the first node is the root package and
+		// tree is already created from it.
+		nextNode = iPackageDlinkFetchIter;
+		}
+	else
+		{
+		// This case should never arise, as the api
+		// should not get called.
+		nextNode = NULL;
+		}
+	return nextNode;
+	}
+
+CPackageInfo* CDepTree::GetFetchNode( TInt nodeLocation)
+	{
+	CPackageInfo* node = NULL;
+
+	if (iFetchList.Count() > nodeLocation )
+		{
+		node = iFetchList[nodeLocation];
+		}
+	return node;
+	}
+
+
+CPackageInfo* CDepTree::GetNextFetchNode()
+	{
+	CPackageInfo* nextNode = NULL;
+
+	if (iFetchList.Count() > (iCurrentPackage+1) )
+		{
+		nextNode = iFetchList[++iCurrentPackage];
+		}
+	return nextNode;
+	}
+
+//TODO: Remove this. this is only for testing purpose.
+//otherwise, there is never a need to get the sorted nodes separately.
+CPackageInfo* CDepTree::GetNextSortedNode()
+	{
+	CPackageInfo* nextNode = NULL;
+
+	if (iSortedList.Count() > (iSortedPackage+1) )
+		{
+		nextNode = iSortedList[++iSortedPackage];
+		}
+	return nextNode;
+	}
+
+CPackageInfo* CDepTree::GetPreviousFetchNode()
+	{
+	CPackageInfo* previousNode = NULL;
+	if (iCurrentPackage > 0)
+		{
+		previousNode = iFetchList[--iCurrentPackage];
+		}
+	 return previousNode;
+	}
+
+void CDepTree::RemoveDownloadedFiles(RFs& aRfs)
+	{
+	CPackageInfo* currentItem;
+	TDblQueIter<CPackageInfo> PackageIter(iPackageDlinkHdr);
+	PackageIter.SetToFirst();
+
+	// Remove all the downloaded dep and changes file
+	while((currentItem = PackageIter) != NULL)
+		{
+		if ( currentItem->iDepFileName )
+			{
+			DeleteFile(aRfs, *(currentItem->iDepFileName), *iDownloadPath);
+			}
+		if ( currentItem->iChangesFileName )
+			{
+			DeleteFile(aRfs, *(currentItem->iChangesFileName), *iDownloadPath);
+			}
+		if ( currentItem->iSisPackageName )
+			{
+			DeleteFile(aRfs, *(currentItem->iSisPackageName), *iDownloadPath);
+			}
+		PackageIter++;
+		}
+	}
+
+void CDepTree::DeleteFile(RFs& aRfs, const TDesC& aFileName, const TDesC& aFilePath )
+	{
+	TFileName filename;
+
+	filename.Copy(aFilePath);
+	filename.Append(aFileName);
+	aRfs.Delete(filename);
+	}
+
+CPackageInfo* CDepTree::GetRootNode()
+	{
+	if (iPackageDlinkHdr.IsEmpty())
+		{
+		return NULL;
+		}
+	else
+		{
+		return iPackageDlinkHdr.First();
+		}
+	}
+
+Edge* Edge::NewLC(CPackageInfo *aVtx1, CPackageInfo *aVtx2)
+	{
+	Edge* object = new ( ELeave ) Edge(aVtx1, aVtx2);
+	CleanupStack::PushL( object );
+	object->ConstructL();
+	return object;
+	}
+
+Edge* Edge::NewL(CPackageInfo *aVtx1, CPackageInfo *aVtx2)
+	{
+	Edge* object = Edge::NewLC(aVtx1, aVtx2);
+	CleanupStack::Pop();
+	return object;
+	}
+
+void Edge::ConstructL()
+	{
+	}
+
+Edge::Edge(CPackageInfo *aVtx1, CPackageInfo *aVtx2)
+	{
+	iVertexOrg = aVtx1;
+	iVertexDst = aVtx2;
+	}
+
+CPackageInfo* Edge::GetVertexOrg() const
+	{
+	return iVertexOrg;
+	}
+
+CPackageInfo* Edge::GetVertexDst() const
+	{
+	return iVertexDst;
+	}