internetradio2.0/cachemgmtsrc/ircachemgmt.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 23 Jun 2010 18:04:00 +0300
changeset 11 f683e24efca3
parent 0 09774dfdd46b
permissions -rw-r--r--
Revision: 201023 Kit: 2010125

/*
* Copyright (c) 2006-2007 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:  ?Description
*
*/


#include <bautils.h>

#include "irbrowsecatagoryitems.h"
#include "irbrowsechannelitems.h"
#include "ircachecleanup.h"
#include "ircachemgmt.h"
#include "ircacheobserver.h"
#include "irdebug.h"
#include "irhttprequestdata.h"
#include "irisdspreset.h"
#include "irotaupdate.h"
#include "irsettings.h"

//Default trust period value.24 hrs in secs with which the object is to be initialised
const TInt KDefaultInterval = 24*60*60;
//granualarity for the arrays
//the granualarity value is based on superficial observation of the amount of 
//data recieved for a particular request
const TInt KBrowseGranualarity = 32;
const TInt KChannelArrayGranualarity = 32;
const TInt KPresetGranualarity = 12;
//http length format length
// "Sun, 06 Nov 1994 08:49:37 GMT" format
const TInt KHttpDateLength = 25;

//Max size(critical size) in Bytes(90% of the max size)
//critical size is the size that triggers cleanup action
const TInt KCacheCriticalSizeLimit = KCacheLimitSize*9/10;

//No of rows deleted will be one fourth of the total number of rows
const TInt KPercentRowsDeleted = 4;  

//The indexing size for the column DataId is set to 100 
const TInt KDataIdIndexSize = 100;

//database file name
_LIT(KCacheDbFile,"cacheDb.db");

//Table Name CacheTable
_LIT(KCacheTable,"CacheTable");

//CacheTable columns
_LIT(KRowIndexCol,     "RowIndex");  
_LIT(KDataTypeCol,     "DataType");            
_LIT(KDataIdCol,       "DataId");       
_LIT(KTrustPeriodCol,  "TrustPeriod");       
_LIT(KLastModifiedCol, "LastModified"); 
_LIT(KLastAccessedCol, "LastAccessed"); 
_LIT(KTimeCreation,    "Created");
_LIT(KItemCount,       "ItemCount");
_LIT(KCachedDataCol,   "CachedData");
_LIT(KETagHeader,      "ETagHeader"); 

//Table Index Names
_LIT(KRowIndexColIndex,     "IndexRowIndex");  
_LIT(KDataTypeColIndex,     "IndexDataType");            
_LIT(KDataIdColIndex,       "IndexDataId");  
_LIT(KLastAccessedColIndex, "IndexLastAccessed"); 
_LIT(KTimeCreationIndex,    "IndexCreated");
//Field Lengths

const TInt KIRObserverArrayGranularity( 2 );


// ---------------------------------------------------------------------------
// Function : OpenL
// Standard two phased construction
// calls ConstructL()
// ---------------------------------------------------------------------------
//
EXPORT_C CIRCacheMgmt* CIRCacheMgmt::OpenL(MIRCacheObserver &aObserver)
	{
	IRLOG_DEBUG( "IRCacheMgmt::OpenL - Entering." );
	CIRCacheMgmt* self = reinterpret_cast<CIRCacheMgmt*>(Dll::Tls());
	
	if (self)
		{
		User::LeaveIfError(self->Open());
		}
    else
		{
		self = new (ELeave) CIRCacheMgmt(aObserver);
		CleanupClosePushL(*self);
		self->ConstructL();
		User::LeaveIfError(Dll::SetTls(self));
		CleanupStack::Pop(self);
		}
	IRLOG_DEBUG( "IRCacheMgmt::OpenL - Exiting." );
	return self;
	}


// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::~CIRCacheMgmt()
// Standard C++ destructor
// ---------------------------------------------------------------------------
//
CIRCacheMgmt::~CIRCacheMgmt() 
	{	
	IRLOG_DEBUG( "IRCacheMgmt::~CIRCacheMgmt - Entering." );
	//array destruction
	if (iPtrPreset)
		{
		iPtrPreset->ResetAndDestroy();
        delete iPtrPreset;
        iPtrPreset = NULL;
		}
    if (iPtrCategory)
        {
        iPtrCategory->ResetAndDestroy();
        }

    delete iPtrCategory;
    iPtrCategory = NULL;
    if (iPtrChannel)
        {
        iPtrChannel->ResetAndDestroy();
        }

    delete iPtrChannel;
    iPtrChannel = NULL;
    if (iSettings)
        {
        iSettings->Close();
        }
	if(iOTA)
		{
		delete iOTA;
		iOTA = NULL;
		}
	iLogoData.Close();		
    CloseDb();
    iCacheDb.Close();
    delete iCleanup;
    iFsSession.Close();
    iCacheObservers.Close();
    Dll::FreeTls();
    IRLOG_DEBUG( "IRCacheMgmt::~CIRCacheMgmt - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CIRCacheMgmt()
// Standard C++ constructor
// sets the trust period to 24hrs(default)
// ---------------------------------------------------------------------------
//
CIRCacheMgmt::CIRCacheMgmt (MIRCacheObserver &aObserver)
			:iCacheObserver(aObserver),
			 iCacheObservers( KIRObserverArrayGranularity )
	{
	IRLOG_DEBUG( "IRCacheMgmt::CIRCacheMgmt - Entering." );
	//default trust period initially set to 24 hrs
	//to be fetched from central repository
	iTrustPeriod = TTimeIntervalSeconds(KDefaultInterval);	
	IRLOG_DEBUG( "IRCacheMgmt::CIRCacheMgmt - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::ConstructL()
// Standard two phased construction
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::ConstructL() 
	{
	IRLOG_DEBUG( "IRCacheMgmt::ConstructL - Entering." );
	User::LeaveIfError(iFsSession.Connect());
	//array construction
	iPtrPreset = new (ELeave) CArrayPtrFlat<CIRIsdsPreset>(
				KPresetGranualarity);
    iPtrCategory = new (ELeave) CArrayPtrFlat<CIRBrowseCatagoryItems>(
    	KBrowseGranualarity);
	iPtrChannel = new (ELeave) CArrayPtrFlat<CIRBrowseChannelItems>(
		KChannelArrayGranualarity);
	iOTA = CIROTAUpdate::NewL();
	iSettings = CIRSettings::OpenL();
	iDatabaseFileName = iSettings->PrivatePath();
	iDatabaseFileName.Append(KCacheDbFile);
	CreateDbConditionalL();
	iCleanup = CIRCacheCleanup::NewL(*this);
	RemoveOtaInfoL();
	IRLOG_DEBUG( "IRCacheMgmt::ConstructL - Exiting." );
    }
    
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CreateDbConditionalL(
// Creates dbms conditionally(only if not yet created)
// calls CreateDb()
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::CreateDbConditionalL()
	{
	IRLOG_DEBUG( "IRCacheMgmt::CreateDbConditionalL - Entering." );
	TInt err=KErrNone;
	if(!BaflUtils::FileExists(iFsSession, iDatabaseFileName))
		{
		err=CreateDb();
		if(KErrNone != err)
			{
			User::Leave(err);	
			}
		}
	IRLOG_DEBUG( "IRCacheMgmt::CreateDbConditionalL - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CreateDb()
// Creates the tables
// ---------------------------------------------------------------------------
//
TInt CIRCacheMgmt::CreateDb()
	{
	IRLOG_DEBUG( "IRCacheMgmt::CreateDb - Entering." );
	CloseDb();
	TInt err=iCacheDb.Replace(iFsSession,iDatabaseFileName);
	if((err!=0))
		{
		return err; //unable to create file	
		}																		
	TRAP(err,//trap start
		CreateCacheTableL();
		CreateCacheIndexL();
		)//trap end
		IRLOG_DEBUG( "IRCacheMgmt::CreateDb - Exiting." );
	return err;
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::OpenCacheDb()
// Opens both the databases 
// ---------------------------------------------------------------------------
//
TInt CIRCacheMgmt::OpenCacheDb()
	{
	IRLOG_DEBUG( "CIRCacheMgmt::OpenCacheDb - Entering" );
	CloseDb();
	TInt error = KErrNone;
	if(!BaflUtils::FileExists(iFsSession, iDatabaseFileName))
	    {
	    //if file doesn't exist function leaves with error code
	    //KErrNotFound
	     return KErrNotFound;
	    }
	//try and open the db	
	error = iCacheDb.Open(iFsSession,iDatabaseFileName);
	//return if error
	if(KErrNone != error )
		{
		return error;
		}
	//check if damaged
	if( iCacheDb.IsDamaged() )
		{
		//if data base is damaged then 
		//try to recover
		error = iCacheDb.Recover();
		return error;
		}
				
	iOpen = ETrue;
	
	IRLOG_DEBUG( "CIRCacheMgmt::OpenCacheDb - Exiting." );
	return KErrNone;
	}
	
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CloseDb()
// Closes the database 
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::CloseDb()
	{
	IRLOG_DEBUG( "IRCacheMgmt::CloseDb - Entering." );
	iCacheDb.Close();
	iOpen = EFalse;
	IRLOG_DEBUG( "IRCacheMgmt::CloseDb - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CheckCache()
// API Exposed to Isds Client to check and get the cached items. 
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRCacheMgmt::CheckCacheL(TInt aType,const TDesC& aName,
					TBool aForceGet,TInt& aReturn)   
	{
	IRLOG_DEBUG( "CIRCacheMgmt::CheckCacheL - Entering" );
	//opens the db if not open already
	if(!iOpen)
		{
		TInt error = OpenCacheDb();
		if(KErrNone != error)
			{
			aReturn = ENotCached;
			return;	
			}
		}

    //calls the function FetchCacheIfAvailable() passing the appropriate type and id
    
	switch(aType)
	{
	case ECatagory:	
	case EChannels:
	case EPresets:
	case EOtaInfo:
	case ELogo:
		{
		TRAP_IGNORE(FetchCacheIfAvailableL(aType,aName,aForceGet,aReturn))
		break;	
		}
		
	default:
		{
	    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
	        {
	        iCacheObservers[i]->CacheFailed();
	        }
		aReturn = ENotCached;
		break;	
		}
	}
	CloseDb();
	IRLOG_DEBUG( "CIRCacheMgmt::CheckCacheL - Exiting." );
	}
	
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::FetchCacheIfAvailable()
// Fetches the cache if available 
// ---------------------------------------------------------------------------
//
//generic function to check the validity of the cache	
void CIRCacheMgmt::FetchCacheIfAvailableL(TInt aType,const TDesC& aId,
	TBool aForceGet,TInt& aReturnVal)
	{
	//Algo****
	//1.check the cache table for a request type
	//2.if the query returns a row,check for validity
	//3.if invalid(stale) do a conditional get
	//4.if valid use cache
	IRLOG_DEBUG( "CIRCacheMgmt::FetchCacheIfAvailableL - Entering" );
	//SELECT * FROM KCacheTable WHERE KDataTypeCol = aType AND KDataIdCol=aId
	_LIT( query, "SELECT * FROM %S WHERE %S = %d AND %S = '%S'" );
	
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KCacheTable().Length() +
								    KDataTypeCol().Length() + KDataIdCol().Length() +
								    KDefaultRealWidth + aId.Length());
								    
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,aType,&KDataIdCol,&aId);
	
	IRLOG_DEBUG2( "CIRCacheMgmt::FetchCacheIfAvailableL - Going to evaluate SQL query: %S", sqlQuery );
	RDbView cacheView;
	User::LeaveIfError(cacheView.Prepare(iCacheDb,*sqlQuery));
	CleanupStack::PopAndDestroy(sqlQuery);
	CleanupClosePushL(cacheView);
    User::LeaveIfError( cacheView.EvaluateAll() );

    //if no row match the query there is no cahche available for that particular 
    //request
    if(cacheView.IsEmptyL())
	    {
	    //Return ENotCached
	    aReturnVal = ENotCached;
	    }
	else
		{
		cacheView.FirstL();
		cacheView.GetL();
		CDbColSet* columns = cacheView.ColSetL();
		TTime creationTime = cacheView.ColTime(columns->ColNo( KTimeCreation));
		TInt cacheValidityTime = cacheView.ColInt(columns->ColNo( KTrustPeriodCol));
		TInt countItems=cacheView.ColInt(columns->ColNo( KItemCount));
		IRLOG_DEBUG( "CIRCacheMgmt::FetchCacheIfAvailableL - can check validity." );
		//check if cache is valid
		//get it any way if it is "forcedget"
		if( aForceGet || CheckValidity(creationTime,cacheValidityTime))
			{
			//Fetch the cached data
			//FetchCachedData(type,count,&view )
			TRAPD(err,FetchCachedDataL(aType,countItems,cacheView));
			if(err!=KErrNone)
				{
				//something goes wrong ,return not cached and fetch new data
				aReturnVal = ENotCached;
				}
			else
				{
				//cache usable
				aReturnVal = ECacheUseable;
				}
			}
		else
			{
			iLastModified = cacheView.ColTime(columns->ColNo( KLastModifiedCol));
			iETag = cacheView.ColDes8(columns->ColNo( KETagHeader ));			
			aReturnVal = ECacheNotValid;
			cacheView.Close();
		    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
		        {
		        iCacheObservers[i]->CacheInvalid();
		        }
			}
	    delete columns;	
		}
	CleanupStack::PopAndDestroy(&cacheView);
	IRLOG_DEBUG( "CIRCacheMgmt::FetchCacheIfAvailableL - Exiting." );
	
	}
	
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::FetchCachedDataL()
// fetches the cached data from the table into the cached structures
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::FetchCachedDataL(TInt aType,TInt aCountItems,RDbView& aCacheView)
	{
	//Algo****
	//fetch the data and internalize into appropriate structure

	IRLOG_DEBUG( "CIRCacheMgmt::FetchCachedDataL - Entering" );
    CDbColSet* columns = aCacheView.ColSetL();
    TInt columnNo = columns->ColNo( KCachedDataCol );
    delete columns;
	switch(aType)
		{
		case ECatagory:
			{
			//Internalize the category items into the CIRBrowseCatagoryItems array
	        RDbColReadStream instream;
	        instream.OpenLC( aCacheView, columnNo );
			CIRBrowseCatagoryItems* ptr;
			if (iPtrCategory)
				{
				iPtrCategory->ResetAndDestroy();
				}
			else
			{
				break;
			}
			for(TInt iter=0;iter<aCountItems;iter++)
				{
				ptr=CIRBrowseCatagoryItems::NewL();
				CleanupStack::PushL(ptr);
				instream>>*ptr;
				iPtrCategory->AppendL(ptr);
				CleanupStack::Pop(ptr);
				}
	        CleanupStack::PopAndDestroy( &instream );
	        //update the last accessed time
	        UpdateLastAccessedTimeL(aCacheView);
	        aCacheView.Close();
		    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
		        {
		        iCacheObservers[i]->CachedStructureL(ECatagory);
		        }
	        break;
			}
		case EChannels:
			{
			//Internalize the channel items into the CIRBrowseChannelItems array
	        RDbColReadStream instream;
	        instream.OpenLC( aCacheView, columnNo );
	        if (iPtrChannel)
				{
				iPtrChannel->ResetAndDestroy();
				}
			CIRBrowseChannelItems *ptr;
			for(TInt iter=0;iter<aCountItems;iter++)
				{
				ptr = CIRBrowseChannelItems::NewL();
				CleanupStack::PushL(ptr);
				instream>>*ptr;
	            if (iPtrChannel)
				    {				
        		    iPtrChannel->AppendL(ptr);
	        		}
				CleanupStack::Pop(ptr);
				}
	        CleanupStack::PopAndDestroy( &instream );
	        //update the last accessed time
	        UpdateLastAccessedTimeL(aCacheView);
	        aCacheView.Close();
		    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
		        {
		        iCacheObservers[i]->CachedStructureL(EChannels);
		        }
	        break;
			}
		case EPresets:
			{
			//Internalize the preset  into the CIRIsdsPreset object
	        RDbColReadStream instream;
	        instream.OpenLC( aCacheView, columnNo );
	        if(iPtrPreset)
		        {
		        iPtrPreset->ResetAndDestroy();
		        }
		    CIRIsdsPreset *ptr;
		    for(TInt iter=0;iter<aCountItems;iter++)
		    	{
		    	ptr = CIRIsdsPreset::NewL();
		    	CleanupStack::PushL(ptr);
		    	instream>>*ptr;
	            if(iPtrPreset)
		            {		    	
		    	    iPtrPreset->AppendL(ptr);
		            }
		    	CleanupStack::Pop(ptr);
		        }
	        CleanupStack::PopAndDestroy( &instream );
	        //update the last accessed time
	        UpdateLastAccessedTimeL(aCacheView);
	        aCacheView.Close();
		    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
		        {
		        iCacheObservers[i]->CachedStructureL(EPresets);
		        }
	        break;
			}
		case EOtaInfo:
			{
			//Internalize the ota info into the CIROTAUpdate object
	        RDbColReadStream instream;
	        instream.OpenLC( aCacheView, columnNo );
	        if(iOTA)
		        {
		        delete iOTA;
		        iOTA = NULL;
		        iOTA = CIROTAUpdate::NewL();
		        instream>>*iOTA;
		        }
		  
	        CleanupStack::PopAndDestroy( &instream );
	        //update the last accessed time
	        UpdateLastAccessedTimeL(aCacheView);
	        aCacheView.Close();
		    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
		        {
		        iCacheObservers[i]->CachedStructureL(EOtaInfo);
		        }
	        break;
			}
		case ELogo:
			{
			//get the logo data from the cache
			TInt logoSize = aCacheView.ColSize(columnNo);
			iLogoData.Close();
			iLogoData.Zero();
			iLogoData.Create(logoSize);
			
			RDbColReadStream instream;
			instream.OpenLC( aCacheView, columnNo );
			instream.ReadL(iLogoData,aCacheView.ColLength(columnNo));
			CleanupStack::PopAndDestroy( &instream );
			//update the last accessed time
	        UpdateLastAccessedTimeL(aCacheView);
			aCacheView.Close();
		    for (TInt i = 0 ; i < iCacheObservers.Count() ; i++ )
		        {
		        iCacheObservers[i]->CachedStructureL(ELogo);
		        }
	        break;
			}
		default:
			{
	        aCacheView.Close();
			}
		}
	IRLOG_DEBUG( "CIRCacheMgmt::FetchCachedDataL - Exiting." );
	}
// ---------------------------------------------------------------------------
//updates the last accessed field to aid in deletion of old unused data
//
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::UpdateLastAccessedTimeL(RDbView &aCacheView)
	{
	IRLOG_DEBUG( "IRCacheMgmt::UpdateTrustPeriod - Entering." );
	//update the last accessed col
	CDbColSet* columns = aCacheView.ColSetL();
    TInt updateColNo = columns->ColNo( KLastAccessedCol );
    delete columns;
    TTime currentTime;
	currentTime.UniversalTime();
    //update the current time value
	aCacheView.GetL();
	aCacheView.UpdateL();
	aCacheView.SetColL(updateColNo,currentTime);
	aCacheView.PutL();
	IRLOG_DEBUG( "IRCacheMgmt::UpdateTrustPeriod - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CheckValidity()
// Checks the freshness of the cache
// ---------------------------------------------------------------------------
//
TBool CIRCacheMgmt::CheckValidity(const TTime& aCreateTime,TInt aTrustPeriod) const
	{
	//Algo****
	//1.get the last creation time from the table for the request
	//2.calculate creation-time + trust-period < current-time *
	//3.if true the cache is valid
	//4.else do conditional-get
	IRLOG_DEBUG( "CIRCacheMgmt::CheckValidity - Entering" );
	TTimeIntervalSeconds trustPeriod(aTrustPeriod);
	TTimeIntervalSeconds diff;
	TTime currentDeviceTime;
	currentDeviceTime.UniversalTime();
	currentDeviceTime.SecondsFrom(aCreateTime,diff);
	//Has the cache expired
		if(diff<trustPeriod)
			{
			IRLOG_DEBUG( "CIRCacheMgmt::CheckValidity - Exiting (1)." );
			return  ETrue;
			}
		//Else return false
		else
			{
			IRLOG_DEBUG( "CIRCacheMgmt::CheckValidity - Exiting (2)." );
			return	EFalse;	
			}
	}


// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CacheCategoryItemsL()
// Caches the category array of data.By externalizing it into a file.
// ---------------------------------------------------------------------------
//

EXPORT_C void CIRCacheMgmt::CacheCategoryItemsL(
					CArrayPtrFlat<CIRBrowseCatagoryItems>& aPtrCategory,
					const TDesC& aName, const CIRHttpResponseData& aResponseHeaders)
	{
	//Algo****
	//1.check if similar request is cached
	//2.delete if similar request is already present
	//3.prepare a view for insertion
	//4.push in the requested data as serialized data
	
	IRLOG_DEBUG( "IRCacheMgmt::CacheCategoryItemsL - Entering" );
	TInt error = OpenCacheDb();
	if(KErrNone != error)
		{
		//no problems if this function returns here.
		//normal flow won't get affected.
		//only a particular request wont get cached
		return;	
		}
	
	//clear similar data from the cache table before updating it with fresh data
	//DELETE FROM KCacheTable WHERE KDataTypeCol = TYPE AND KDataIdCol = DATAID 
	_LIT(query,"DELETE FROM %S WHERE %S = %d AND %S = '%S'");
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDataIdCol().Length() +
									KDefaultRealWidth + aName.Length());
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,ECatagory,&KDataIdCol,&aName);
	iCacheDb.Begin();
	//deletes a similar record if it existed.
	//no problem if it did not exist
	iCacheDb.Execute(*sqlQuery,EDbCompareNormal);
	CleanupStack::PopAndDestroy(sqlQuery);
	iCacheDb.Commit();
	
	//get the cached data view for preset column to update with fresh data.
	//SELECT * FROM KCacheTable WHERE KDataTypeCol = TYPE
	_LIT(query1,"SELECT * FROM %S WHERE %S = %d");
	HBufC* sqlQuery1 = HBufC::NewLC(query1().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDefaultRealWidth);
	sqlQuery1->Des().Format(query1,&KCacheTable,&KDataTypeCol,ECatagory);
	
	RDbView cacheTableView;
	User::LeaveIfError(cacheTableView.Prepare(iCacheDb,*sqlQuery1));
	CleanupStack::PopAndDestroy(sqlQuery1);
	CleanupClosePushL(cacheTableView);
	
	User::LeaveIfError(cacheTableView.EvaluateAll());

	//prepare insertion values
	//will go into last accessed aswell as the creation time fields
	TTime currentTime;
	currentTime.UniversalTime();
	TInt countItems=aPtrCategory.Count();
	TInt maxAge;
	if(aResponseHeaders.iMaxAge.Length() == 0)
		{
		maxAge=iTrustPeriod.Int();
		}
	else
		{
		TLex8 conv(aResponseHeaders.iMaxAge);
		conv.Val(maxAge);	
		maxAge = maxAge * KDefaultInterval;
		}
    CDbColSet* columns = cacheTableView.ColSetL();
    CleanupStack::PushL(columns);
	//write stream
	RDbColWriteStream writeStream;
	//start insertion into the view
	//insert a new row
	cacheTableView.InsertL();
	//set values
	cacheTableView.SetColL(columns->ColNo(KDataTypeCol), ECatagory);
	cacheTableView.SetColL(columns->ColNo(KDataIdCol), aName);
	cacheTableView.SetColL(columns->ColNo(KTrustPeriodCol), maxAge);
	cacheTableView.SetColL(columns->ColNo(KItemCount), countItems);
	//to be set only if available
	cacheTableView.SetColL(columns->ColNo(KLastModifiedCol),aResponseHeaders.iLastModified);
	cacheTableView.SetColL(columns->ColNo(KLastAccessedCol), currentTime);
	cacheTableView.SetColL(columns->ColNo(KTimeCreation), currentTime);
	//open stream
	writeStream.OpenLC(cacheTableView,columns->ColNo(KCachedDataCol));
	for(TInt iter=0;iter<countItems;iter++)
		{
		aPtrCategory[iter]->ExternalizeL(writeStream);
		}	
	writeStream.CommitL();
	CleanupStack::PopAndDestroy(&writeStream);
	cacheTableView.PutL();
	CleanupStack::PopAndDestroy(columns);
	CleanupStack::PopAndDestroy(&cacheTableView);
	CloseDb();
	IRLOG_DEBUG( "IRCacheMgmt::CacheCategoryItemsL - Exiting." );
	
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CacheChannelItemsL()
// Caches the channel objects array of data.By externalizing it into a file..
// ---------------------------------------------------------------------------
//

EXPORT_C void CIRCacheMgmt::CacheChannelItemsL(CArrayPtrFlat<CIRBrowseChannelItems>& aPtrChannel,
											   const TDesC& aName,const CIRHttpResponseData& aResponseHeaders)
	{
	//Algo****
	//1.check if similar request is cached
	//2.delete if similar request is already present
	//3.prepare a view for insertion
	//4.push in the cached data request as serialized data
	IRLOG_DEBUG( "CIRCacheMgmt::CacheChannelItemsL - Entering" );

	TInt error = OpenCacheDb();
	if(KErrNone != error)
		{
		//no problems if this function returns here.
		//normal flow won't get affected.
		//only a particular request wont get cached
		return;	
		}
	
	//convert the id information of descriptor to int value for comparision
	//clear data from the cache table before updating it with fresh data
	//DELETE FROM KCacheTable WHERE KDataTypeCol = TYPE AND KDataIdCol = DATAID 
	_LIT(query,"DELETE FROM %S WHERE %S = %d AND %S = '%S'");
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDataIdCol().Length() +
									KDefaultRealWidth + aName.Length());
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,EChannels,&KDataIdCol,&aName);
	iCacheDb.Begin();
	//deletes a similar record if it existed.
	//no problem if it did not exist
	iCacheDb.Execute(*sqlQuery,EDbCompareNormal);
	CleanupStack::PopAndDestroy(sqlQuery);
	iCacheDb.Commit();
	
	//get the cached data view for preset column to update with fresh data.
	//SELECT * FROM KCacheTable WHERE KDataTypeCol = TYPE
	_LIT(query1,"SELECT * FROM %S WHERE %S = %d");
	HBufC* sqlQuery1 = HBufC::NewLC(query1().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDefaultRealWidth);
	RDbView cacheTableView;
	sqlQuery1->Des().Format(query1,&KCacheTable,&KDataTypeCol,EChannels);	
	User::LeaveIfError(cacheTableView.Prepare(iCacheDb,*sqlQuery1));
	CleanupStack::PopAndDestroy(sqlQuery1);
	CleanupClosePushL(cacheTableView);
	
	User::LeaveIfError(cacheTableView.EvaluateAll());

	//prepare insertion values
	//will go into last accessed aswell as the creation time fields
	TTime currentTime;
	currentTime.UniversalTime();
	TInt countItems=aPtrChannel.Count();
	TInt maxAge;
	if(aResponseHeaders.iMaxAge.Length() == 0)
		{
		maxAge=iTrustPeriod.Int();
		}
	else
		{
		TLex8 conv(aResponseHeaders.iMaxAge);
		conv.Val(maxAge);	
		maxAge = maxAge * KDefaultInterval;
		}
	TBuf<KHttpDateLength>lastModified;

    CDbColSet* columns = cacheTableView.ColSetL();
    CleanupStack::PushL(columns);
	//write stream
	RDbColWriteStream writeStream;
	
	//start insertion into the view
	//insert a new row
	cacheTableView.InsertL();
	//set values
	cacheTableView.SetColL(columns->ColNo(KDataTypeCol), EChannels);
	cacheTableView.SetColL(columns->ColNo(KDataIdCol), aName);
	cacheTableView.SetColL(columns->ColNo(KTrustPeriodCol), maxAge);
	cacheTableView.SetColL(columns->ColNo(KItemCount), countItems);
	//to be set only if available
	cacheTableView.SetColL(columns->ColNo(KLastModifiedCol),aResponseHeaders.iLastModified);
	//
	cacheTableView.SetColL(columns->ColNo(KLastAccessedCol), currentTime);
	cacheTableView.SetColL(columns->ColNo(KTimeCreation), currentTime);
	//open stream
	writeStream.OpenLC(cacheTableView,columns->ColNo(KCachedDataCol));
	for(TInt iter=0;iter<countItems;iter++)
		{
		aPtrChannel[iter]->ExternalizeL(writeStream);
		}	
	writeStream.CommitL();
	CleanupStack::PopAndDestroy(&writeStream);
	cacheTableView.PutL();
	CleanupStack::PopAndDestroy(columns);
	CleanupStack::PopAndDestroy(&cacheTableView);
	CloseDb();
	IRLOG_DEBUG( "CIRCacheMgmt::CacheChannelItemsL - Exiting." );
	
	}

// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CachePresetItemL()
// Caches the preset object .By externalizing it into a file.
//multiple presets can be cached at one time
// ---------------------------------------------------------------------------
//

EXPORT_C void CIRCacheMgmt::CachePresetItemL(CArrayPtrFlat<CIRIsdsPreset>& aPtrPresets,
				const TDesC& aName,const CIRHttpResponseData& aResponseHeaders)
	{
	//Algo****
	//1.check if similar request is cached
	//2.delete if similar request is already present
	//3.prepare a view for insertion
	//4.push in the cached data request as serialized data
	IRLOG_DEBUG( "CIRCacheMgmt::CachePresetItemL - Entering" );

	TInt error = OpenCacheDb();
	if(KErrNone != error)
		{
		//no problems if this function returns here.
		//normal flow won't get affected.
		//only a particular request wont get cached
		return;	
		}
	//convert the id information of descriptor to int value for comparision
	//clear data from the cache table before updating it with fresh data
	//DELETE FROM KCacheTable WHERE KDataTypeCol = TYPE AND KDataIdCol = DATAID 
	_LIT(query,"DELETE FROM %S WHERE %S = %d AND %S = '%S'");
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDataIdCol().Length() +
									KDefaultRealWidth + aName.Length());
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,EPresets,&KDataIdCol,&aName);
	iCacheDb.Begin();
	//deletes a similar record if it existed.
	//no problem if it did not exist
	iCacheDb.Execute(*sqlQuery,EDbCompareNormal);
	CleanupStack::PopAndDestroy(sqlQuery);
	iCacheDb.Commit();
	
	//get the cached data view for preset column to update with fresh data.
	//SELECT * FROM KCacheTable WHERE KDataTypeCol = TYPE
	_LIT(query1,"SELECT * FROM %S WHERE %S = %d");
	HBufC* sqlQuery1 = HBufC::NewLC(query1().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDefaultRealWidth);
	sqlQuery1->Des().Format(query1,&KCacheTable,&KDataTypeCol,EPresets);	
	RDbView cacheTableView;
	User::LeaveIfError(cacheTableView.Prepare(iCacheDb,*sqlQuery1));
	CleanupStack::PopAndDestroy(sqlQuery1);
	CleanupClosePushL(cacheTableView);
	
	User::LeaveIfError(cacheTableView.EvaluateAll());

	//prepare insertion values
	//will go into last accessed aswell as the creation time fields
	TTime currentTime;
	currentTime.UniversalTime();
	
	TInt maxAge;
	if(aResponseHeaders.iMaxAge.Length()== 0)
		{
		maxAge=iTrustPeriod.Int();
		}
	else
		{
		TLex8 conv(aResponseHeaders.iMaxAge);
		conv.Val(maxAge);	
		maxAge = maxAge * KDefaultInterval;
		}
	TBuf<KHttpDateLength>lastModified;
	//default time set to 24hrs
	//use iTrustPeriod
	//type set to EPresets
	//id set to dataId
	//last modified time kept null
	//item count set to 1
    CDbColSet* columns = cacheTableView.ColSetL();
    CleanupStack::PushL(columns);
	//write stream
	RDbColWriteStream writeStream;
	TInt countItems;
	countItems = aPtrPresets.Count();
	//start insertion into the view
	//insert a new row
	cacheTableView.InsertL();
	//set values
	cacheTableView.SetColL(columns->ColNo(KDataTypeCol), EPresets);
	cacheTableView.SetColL(columns->ColNo(KDataIdCol), aName);
	cacheTableView.SetColL(columns->ColNo(KTrustPeriodCol), maxAge);
	cacheTableView.SetColL(columns->ColNo(KItemCount), countItems);
	//to be set only if available
	cacheTableView.SetColL(columns->ColNo(KLastModifiedCol),
		aResponseHeaders.iLastModified);
	//
	cacheTableView.SetColL(columns->ColNo(KLastAccessedCol), currentTime);
	cacheTableView.SetColL(columns->ColNo(KTimeCreation), currentTime);
	//open stream
	writeStream.OpenLC(cacheTableView,columns->ColNo(KCachedDataCol));
	for(TInt iter=0;iter<countItems;iter++)
		{
		aPtrPresets[iter]->ExternalizeL(writeStream);
		}
	writeStream.CommitL();
	CleanupStack::PopAndDestroy(&writeStream);
	cacheTableView.PutL();
		
	CleanupStack::PopAndDestroy(columns);
	CleanupStack::PopAndDestroy(&cacheTableView);
	CloseDb();
	IRLOG_DEBUG( "CIRCacheMgmt::CachePresetItemL - Exiting." );
	}
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CacheOtaInfoL()
// Caches the OTA information  .By externalizing it into a db.
// ---------------------------------------------------------------------------
//

EXPORT_C void CIRCacheMgmt::CacheOtaInfoL(const CIROTAUpdate& aOta,const TDesC& aName,
										const CIRHttpResponseData& aResponseHeaders)
	{
	//Algo****
	//1.check if similar request is cached
	//2.delete if similar request is already present
	//3.prepare a view for insertion
	//4.push in the cached data request as serialized data
	IRLOG_DEBUG( "CIRCacheMgmt::CacheOtaInfoL - Entering" );

	TInt error = OpenCacheDb();
	if(KErrNone != error)
		{
		//no problems if this function returns here.
		//normal flow won't get affected.
		//only a particular request wont get cached
		return;	
		}
	//convert the id information of descriptor to int value for comparision
	//clear data from the cache table before updating it with fresh data
	//DELETE FROM KCacheTable WHERE KDataTypeCol = TYPE AND KDataIdCol = DATAID 
	_LIT(query,"DELETE FROM %S WHERE %S = %d AND %S = '%S'");
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDataIdCol().Length() +
									KDefaultRealWidth + aName.Length());
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,EOtaInfo,&KDataIdCol,&aName);
	User::LeaveIfError(iCacheDb.Begin());
	//deletes a similar record if it existed.
	//no problem if it did not exist
	iCacheDb.Execute(*sqlQuery,EDbCompareNormal);
	CleanupStack::PopAndDestroy(sqlQuery);
	iCacheDb.Commit();
	
	//get the cached data view for preset column to update with fresh data.
	//SELECT * FROM KCacheTable WHERE KDataTypeCol = TYPE
	_LIT(query1,"SELECT * FROM %S WHERE %S = %d");
	HBufC* sqlQuery1 = HBufC::NewLC(query1().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDefaultRealWidth);
	sqlQuery1->Des().Format(query1,&KCacheTable,&KDataTypeCol,EOtaInfo);	
	RDbView cacheTableView;
	User::LeaveIfError(cacheTableView.Prepare(iCacheDb,*sqlQuery1));
	CleanupStack::PopAndDestroy(sqlQuery1);
	CleanupClosePushL(cacheTableView);
	
	User::LeaveIfError(cacheTableView.EvaluateAll());

	//prepare insertion values
	//will go into last accessed aswell as the creation time fields
	TTime currentTime;
	currentTime.UniversalTime();
	
	TInt maxAge;
	if(aResponseHeaders.iMaxAge.Length()== 0)
		{
		maxAge=iTrustPeriod.Int();
		}
	else
		{
		TLex8 conv(aResponseHeaders.iMaxAge);
		conv.Val(maxAge);	
		maxAge = maxAge * KDefaultInterval;
		}
	TBuf<KHttpDateLength>lastModified;
	//default time set to 24hrs
	//use iTrustPeriod
	//type set to EPresets
	//id set to dataId
	//last modified time kept null
	//item count set to 1
    CDbColSet* columns = cacheTableView.ColSetL();
    CleanupStack::PushL(columns);
	//write stream
	RDbColWriteStream writeStream;
	//start insertion into the view
	//insert a new row
	cacheTableView.InsertL();
	//set values
	cacheTableView.SetColL(columns->ColNo(KDataTypeCol), EOtaInfo);
	cacheTableView.SetColL(columns->ColNo(KDataIdCol), aName);
	cacheTableView.SetColL(columns->ColNo(KTrustPeriodCol), maxAge);
	cacheTableView.SetColL(columns->ColNo(KItemCount), 1);
	//to be set only if available
	cacheTableView.SetColL(columns->ColNo(KLastModifiedCol),
		aResponseHeaders.iLastModified);
	//
	cacheTableView.SetColL(columns->ColNo(KLastAccessedCol), currentTime);
	cacheTableView.SetColL(columns->ColNo(KTimeCreation), currentTime);
	//open stream
	writeStream.OpenLC(cacheTableView,columns->ColNo(KCachedDataCol));
	aOta.ExternalizeL(writeStream);
	writeStream.CommitL();
	CleanupStack::PopAndDestroy(&writeStream);
	cacheTableView.PutL();
		
	CleanupStack::PopAndDestroy(columns);
	CleanupStack::PopAndDestroy(&cacheTableView);
	CloseDb();
	IRLOG_DEBUG( "CIRCacheMgmt::CacheOtaInfoL - Exiting." );
	}
	
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CacheLogoL()
// Caches the logo data  .By externalizing it into a db.
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRCacheMgmt::CacheLogoL(const TDesC8& aData, const TDesC& aUrl,
	                         const CIRHttpResponseData& aResponseHeaders)
	{
	//Algo****
	//1.check if similar request is cached
	//2.delete if similar request is already present
	//3.prepare a view for insertion
	//4.push in the cached data request as serialized data
	IRLOG_DEBUG( "CIRCacheMgmt::CacheLogoL - Entering" );
	
	
	TInt error = OpenCacheDb();
	if(KErrNone != error)
		{
		//no problems if this function returns here.
		//normal flow won't get affected.
		//only a particular request wont get cached
		return;	
		}
	//convert the id information of descriptor to int value for comparision
	//clear data from the cache table before updating it with fresh data
	//DELETE FROM KCacheTable WHERE KDataTypeCol = TYPE AND KDataIdCol = DATAID 
	_LIT(query,"DELETE FROM %S WHERE %S = %d AND %S = '%S'");
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDataIdCol().Length() +
									KDefaultRealWidth + aUrl.Length());
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,ELogo,&KDataIdCol,&aUrl);
	iCacheDb.Begin();
	//deletes a similar record if it existed.
	//no problem if it did not exist
	iCacheDb.Execute(*sqlQuery,EDbCompareNormal);
	CleanupStack::PopAndDestroy(sqlQuery);
	iCacheDb.Commit();	
	
	//get the cached data view for preset column to update with fresh data.
	//SELECT * FROM KCacheTable WHERE KDataTypeCol = TYPE
	_LIT(query1,"SELECT * FROM %S WHERE %S = %d");
	HBufC* sqlQuery1 = HBufC::NewLC(query1().Length() + KDataTypeCol().Length() +
									KCacheTable().Length() + KDefaultRealWidth);
	sqlQuery1->Des().Format(query1,&KCacheTable,&KDataTypeCol,ELogo);	
	RDbView cacheTableView;
	User::LeaveIfError(cacheTableView.Prepare(iCacheDb,*sqlQuery1));
	CleanupStack::PopAndDestroy(sqlQuery1);
	CleanupClosePushL(cacheTableView);
	
	User::LeaveIfError(cacheTableView.EvaluateAll());		
	
	//prepare insertion values
	//will go into last accessed aswell as the creation time fields
	TTime currentTime;
	currentTime.UniversalTime();
	
	TInt maxAge;
	if(aResponseHeaders.iMaxAge.Length()== 0)
		{
		maxAge=iTrustPeriod.Int();
		}
	else
		{
		TLex8 conv(aResponseHeaders.iMaxAge);
		conv.Val(maxAge);	
		maxAge = maxAge * KDefaultInterval;
		}
	TBuf<KHttpDateLength>lastModified;
	//default time set to 24hrs
	//use iTrustPeriod
	//type set to ELogo
	//id set to dataId
	//last modified time kept null
	//item count set to 1
    CDbColSet* columns = cacheTableView.ColSetL();
    CleanupStack::PushL(columns);
	//write stream
	//start insertion into the view
	//insert a new row
	cacheTableView.InsertL();
	//set values
	cacheTableView.SetColL(columns->ColNo(KDataTypeCol), ELogo);
	cacheTableView.SetColL(columns->ColNo(KDataIdCol), aUrl);
	cacheTableView.SetColL(columns->ColNo(KTrustPeriodCol), maxAge);
	cacheTableView.SetColL(columns->ColNo(KItemCount), 1);
	//to be set only if available
	cacheTableView.SetColL(columns->ColNo(KLastModifiedCol),
		aResponseHeaders.iLastModified);
	//
	cacheTableView.SetColL(columns->ColNo(KLastAccessedCol), currentTime);
	cacheTableView.SetColL(columns->ColNo(KTimeCreation), currentTime);
	cacheTableView.SetColL(columns->ColNo(KCachedDataCol), aData);
	
	cacheTableView.SetColL(columns->ColNo(KETagHeader), 
	    aResponseHeaders.iETag);
	
	cacheTableView.PutL();

		
	CleanupStack::PopAndDestroy(columns);
	CleanupStack::PopAndDestroy(&cacheTableView);
	CloseDb();
	IRLOG_DEBUG( "CIRCacheMgmt::CacheLogoL - Exiting." );					
			
	}
	
	
	
	
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CreateCacheTableL()
// creates the cache table
// ---------------------------------------------------------------------------
//
//CacheTable
// -----------------------------------------------------------------------------------------------------
//| RowIndex|DataType|DataId|TrustPeriod|LastModified  |LastAccessed|Created|ItemCount|CachedData|
//------------------------------------------------------------------------------------------------
//| auto    |TInt    |DesC  |TInt       |TDesC/DateTime|TTime       |Time   |TInt     | Streamed |
//|increment|0,1,2,NotNull|NotNull|  NotNull  |              |            |       |         | Data     |
//------------------------------------------------------------------------------------------------------
void CIRCacheMgmt::CreateCacheTableL()
	{
	IRLOG_DEBUG( "IRCacheMgmt::CreateCacheTableL - Entering." );
	//the row index column which autoincrements
	TDbCol rowIndexCol(KRowIndexCol, EDbColInt32);   
    rowIndexCol.iAttributes = TDbCol::EAutoIncrement;
    
    //the datatype column,to identify between 	ECatagory = 0,EChannels=1,EPresets=2
    TDbCol dataTypeCol(KDataTypeCol, EDbColInt32);
    dataTypeCol.iAttributes = TDbCol::ENotNull;
     
    //the dataID column,to uniquely identify the cached data
    TDbCol dataId(KDataIdCol, EDbColLongText16);
    dataId.iAttributes = TDbCol::ENotNull; 
    
    //the trust period column to calculate cache validity
    TDbCol trustPeriodCol(KTrustPeriodCol, EDbColInt32);
    
    //the lastmodified column to fetch data conditionally
    TDbCol lastModifiedCol(KLastModifiedCol, EDbColDateTime);

    
    //the last accessed column used for table clean-up
    TDbCol creationTimeCol(KTimeCreation, EDbColDateTime);
	    
    //the time of creation saved to calculate the cache validity
    TDbCol lastAccessedCol(KLastAccessedCol, EDbColDateTime);
    
	//the number of items in the data field
    TDbCol itemCountCol(KItemCount, EDbColInt32);
    
    //the data column to store cached data
    //The column stores a potentially large amount of Unicode text data.
    TDbCol cachedDataCol(KCachedDataCol, EDbColLongText8);
    
    //the ETag header received along with the logo data
    TDbCol etagHeader(KETagHeader, EDbColText8);
    
    //colset
    CDbColSet* cacheTablerColSet = CDbColSet::NewLC();
    //populate colset
	 cacheTablerColSet->AddL(rowIndexCol);
	 cacheTablerColSet->AddL(dataTypeCol);
	 cacheTablerColSet->AddL(dataId);
	 cacheTablerColSet->AddL(trustPeriodCol);
	 cacheTablerColSet->AddL(lastModifiedCol);
	 cacheTablerColSet->AddL(creationTimeCol);
	 cacheTablerColSet->AddL(lastAccessedCol);
	 cacheTablerColSet->AddL(itemCountCol);
	 cacheTablerColSet->AddL(cachedDataCol);
	 cacheTablerColSet->AddL(etagHeader);

    // Create the CacheTable table
    User::LeaveIfError(iCacheDb.CreateTable(KCacheTable, *cacheTablerColSet));
    
    CleanupStack::PopAndDestroy(cacheTablerColSet);	
    IRLOG_DEBUG( "IRCacheMgmt::CreateCacheTableL - Exiting." );
	}
	
// ---------------------------------------------------------------------------
// Function : CIRCacheMgmt::CreateCacheIndexL()
// creates the indices for cache table
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::CreateCacheIndexL()
	{
	IRLOG_DEBUG( "IRCacheMgmt::CreateCacheIndexL - Entering." );
	TDbKeyCol rowIndexCol(KRowIndexCol);
	TDbKeyCol dataTypeCol(KDataTypeCol);
	TDbKeyCol dataIdCol(KDataIdCol,KDataIdIndexSize);
	TDbKeyCol timeCreationCol(KTimeCreation);
	TDbKeyCol lastAccessedCol(KLastAccessedCol);
	 
	CDbKey* index;
	//index on the auto increment row id
	index = CDbKey::NewLC();   
	index->AddL(rowIndexCol);
	User::LeaveIfError(iCacheDb.CreateIndex(KRowIndexColIndex, KCacheTable,
		 *index));
	CleanupStack::PopAndDestroy(index);
	
	//index on the datatype column
	index = CDbKey::NewLC();   
	index->AddL(dataTypeCol);
	User::LeaveIfError(iCacheDb.CreateIndex(KDataTypeColIndex, KCacheTable, 
		*index));
	CleanupStack::PopAndDestroy(index);
	
	//index on the data id column
	index = CDbKey::NewLC();   
	index->AddL(dataIdCol);
	User::LeaveIfError(iCacheDb.CreateIndex(KDataIdColIndex, KCacheTable, 
		*index));
	CleanupStack::PopAndDestroy(index);
	
	//index on the time of record creation column
	index = CDbKey::NewLC();   
	index->AddL(timeCreationCol);
	User::LeaveIfError(iCacheDb.CreateIndex(KTimeCreationIndex, KCacheTable, 
		*index));
	CleanupStack::PopAndDestroy(index);
	
	//index on the last accessed column
	index = CDbKey::NewLC();   
	index->AddL(lastAccessedCol);
	User::LeaveIfError(iCacheDb.CreateIndex(KLastAccessedColIndex, KCacheTable,
		 *index));
	CleanupStack::PopAndDestroy(index);
	IRLOG_DEBUG( "IRCacheMgmt::CreateCacheIndexL - Exiting." );
	}
// ---------------------------------------------------------------------------
//void CIRCacheMgmt::UpdateTrustPeriod()
//updates the trust period for a not-modified responce
// ---------------------------------------------------------------------------

//
EXPORT_C void CIRCacheMgmt::UpdateTrustPeriodL(	TInt aType, const TDesC& aName,
	CIRHttpResponseData& aResponseHeaders)
	{	
	IRLOG_DEBUG( "IRCacheMgmt::UpdateTrustPeriodL - Entering" );
	TInt error = OpenCacheDb();
	if(KErrNone != error)
		{
	    IRLOG_ERROR2( "IRCacheMgmt::UpdateTrustPeriodL - Error while opening cache DB (%d).", error );			
		//no problems if this function returns here.
		//normal flow won't get affected.
		//only a particular request wont get cached
		return;	
		}

	//SELECT * FROM KCacheTable WHERE KDataTypeCol = TYPE AND KDataIdCol = DATAID 
	_LIT(query,"SELECT * FROM %S WHERE %S = %d AND %S = '%S'");
	HBufC* sqlQuery = HBufC::NewLC(query().Length() + KCacheTable().Length() +
		 KDataIdCol().Length() + KDataTypeCol().Length() + aName.Length()+
		 KDefaultRealWidth );
		 
	sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,aType,&KDataIdCol,&aName);
	//create view
	RDbView cacheTableView;
	User::LeaveIfError(cacheTableView.Prepare(iCacheDb,*sqlQuery));
	CleanupStack::PopAndDestroy(sqlQuery);
	CleanupClosePushL(cacheTableView);
	
	User::LeaveIfError(cacheTableView.EvaluateAll());
	
	//prepare the update data
	//will go into last accessed aswell as the creation time fields
	TTime currentTime;
	currentTime.UniversalTime();
	//get the new trust period from the headers
	TInt maxAge;
	if(aResponseHeaders.iMaxAge.Length() == 0)
		{
		maxAge=iTrustPeriod.Int();
		}
	else
		{
		TLex8 conv(aResponseHeaders.iMaxAge);
		conv.Val(maxAge);	
		maxAge = maxAge * KDefaultInterval;
		}
    CDbColSet* columns = cacheTableView.ColSetL();
    CleanupStack::PushL(columns);
	cacheTableView.FirstL();
	if(cacheTableView.AtRow())
		{
		cacheTableView.UpdateL();
		//update values
		cacheTableView.SetColL(columns->ColNo(KTrustPeriodCol), maxAge);
		cacheTableView.SetColL(columns->ColNo(KLastAccessedCol), currentTime);
		cacheTableView.SetColL(columns->ColNo(KTimeCreation), currentTime);
		cacheTableView.PutL();
		}

	CleanupStack::PopAndDestroy(columns);
	CleanupStack::PopAndDestroy(&cacheTableView);
	CloseDb();
	IRLOG_DEBUG( "IRCacheMgmt::UpdateTrustPeriod - Exiting." );	
	}
	
// ---------------------------------------------------------------------------
//  Used to dcontrol the cache table size by compacting and clearing up unused items
// ---------------------------------------------------------------------------
//
 void CIRCacheMgmt::CheckSizeL()
 	{
 	IRLOG_DEBUG( "IRCacheMgmt::CheckSizeL - Entering." );
 	OpenCacheDb();
 	RDbDatabase::TSize dbSize = iCacheDb.Size();
 	iCacheDbSize = dbSize.iSize;
 	TInt size = CacheSize();
 	if( size >= KCacheCriticalSizeLimit )
 		{
 		RemoveOldUnusedDataL();
 		OpenCacheDb();
 		iCacheDb.Compact();
 		//refresh the size information
 		dbSize = iCacheDb.Size();
 		iCacheDbSize = dbSize.iSize;
 		}
	CloseDb();
	IRLOG_DEBUG( "IRCacheMgmt::CheckSizeL - Exiting." );
 	}

// ---------------------------------------------------------------------------
// Used to control the cache table size by compacting and clearing up unused items
// ---------------------------------------------------------------------------
//
void CIRCacheMgmt::RemoveOldUnusedDataL()
	{
	IRLOG_DEBUG( "IRCacheMgmt::RemoveOldUnusedDataL - Entering." );
	OpenCacheDb();
	RDbTable cacheTable;
	//open the table in updatable mode
	User::LeaveIfError(cacheTable.Open(iCacheDb, KCacheTable, cacheTable.EUpdatable));
	CleanupClosePushL(cacheTable);
	cacheTable.Reset();
	//set index as the last accessed time
	cacheTable.SetIndex(KLastAccessedCol);
	//begin transaction
	iCacheDb.Begin();
	// no of rows deleted is one fourth of the total number of rows
	TInt deleteRows = cacheTable.CountL()/KPercentRowsDeleted;
	TInt inc = 0;
	//delete incrementally
	for(cacheTable.FirstL();((inc < deleteRows) && cacheTable.AtRow());inc++)
		{
		cacheTable.GetL();
		cacheTable.DeleteL();
		cacheTable.NextL();
		}
	//commit transaction
	iCacheDb.Commit();
	CleanupStack::PopAndDestroy(&cacheTable);
	CloseDb();
	IRLOG_DEBUG( "IRCacheMgmt::RemoveOldUnusedDataL - Exiting." );
	}
	
// ---------------------------------------------------------------------------
// Used to get the cache table size
// ---------------------------------------------------------------------------
//
TInt CIRCacheMgmt::CacheSize()
	{
	IRLOG_DEBUG( "IRCacheMgmt::CacheSize - Entering." );
	OpenCacheDb();
 	RDbDatabase::TSize dbSize = iCacheDb.Size();
 	iCacheDbSize = dbSize.iSize;
 	CloseDb();
 	IRLOG_DEBUG( "IRCacheMgmt::CacheSize - Exiting." );
	return iCacheDbSize;
	}
// ---------------------------------------------------------------------------
//remove OTA info from cache if data is not valid any longer
// ---------------------------------------------------------------------------
EXPORT_C void CIRCacheMgmt::RemoveOtaInfoL()
	{
	IRLOG_DEBUG( "IRCacheMgmt::RemoveOtaInfoL - Entering." );
	//check if the silence period param is set.
	//if not set that means the cached ota info if present is not valid.
	if(iSettings->GetSilencePeriodL() == 0)
		{
		TInt error = OpenCacheDb();
		if(KErrNone != error)
			{
			//no problems if this function returns here.
			//normal flow won't get affected.
			//only a particular request wont get cached
			return;	
			}
		//clear data from the cache table 
		//DELETE FROM KCacheTable WHERE KDataTypeCol = TYPE 
		_LIT(query,"DELETE FROM %S WHERE %S = %d");
		HBufC* sqlQuery = HBufC::NewLC(query().Length() + KDataTypeCol().Length() +
										KCacheTable().Length() + KDataIdCol().Length());
		sqlQuery->Des().Format(query,&KCacheTable,&KDataTypeCol,EOtaInfo);
		User::LeaveIfError(iCacheDb.Begin());
		//no problem if it did not exist
		iCacheDb.Execute(*sqlQuery,EDbCompareNormal);
		CleanupStack::PopAndDestroy(sqlQuery);
		iCacheDb.Commit();
        CloseDb();
		}
	IRLOG_DEBUG( "IRCacheMgmt::RemoveOtaInfoL - Exiting." );
	}



// ---------------------------------------------------------------------------
// Adds a cache observer
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRCacheMgmt::AddObserverL( MIRCacheObserver* aObserver )
    {
    IRLOG_DEBUG( "IRCacheMgmt::AddObserverL - Entering." );
    iCacheObservers.AppendL( aObserver );
    IRLOG_DEBUG( "IRCacheMgmt::AddObserverL - Exiting." );
    }

// ---------------------------------------------------------------------------
// Removes a cache observer
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRCacheMgmt::RemoveObserver( MIRCacheObserver* aObserver )
    {
    IRLOG_DEBUG( "IRCacheMgmt::RemoveObserver - Entering." );
    TInt objectIndex = iCacheObservers.Find( aObserver );
    
    if ( objectIndex != KErrNotFound )
        {
        iCacheObservers.Remove( objectIndex );
        }
    IRLOG_DEBUG( "IRCacheMgmt::RemoveObserver - Exiting." );
    }