internetradio2.0/ircachemgmt/src/ircachemgmt.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 18 Aug 2010 09:40:26 +0300
changeset 14 896e9dbc5f19
permissions -rw-r--r--
Revision: 201031 Kit: 201033

/*
* 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.CreateL( 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." );
    }