xdmprotocols/XcapProtocol/XcapCache/Server/src/XcapCacheSession.cpp
changeset 0 c8caa15ef882
child 12 e6a66db4e9d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xdmprotocols/XcapProtocol/XcapCache/Server/src/XcapCacheSession.cpp	Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,588 @@
+/*
+* Copyright (c) 2005 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:   CXcapCacheSession
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <f32file.h>
+#include <badesca.h>
+#include "XcapCacheIndex.h"
+#include "XcapCacheSession.h"
+#include "XcapCacheIndexAdmin.h"
+#include "XcapCacheIndexEntry.h"
+#include "XcapCacheIndexTableEntry.h"
+
+// ================= MEMBER FUNCTIONS =======================
+//
+
+// ----------------------------------------------------------
+// CXcapCacheSession::NewL
+// 
+// ----------------------------------------------------------
+//
+CXcapCacheSession* CXcapCacheSession::NewL( CXcapCacheServer* aServer )
+    {
+    CXcapCacheSession* self = new( ELeave ) CXcapCacheSession( aServer );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::~CXcapCacheSession
+// 
+// ----------------------------------------------------------
+//
+CXcapCacheSession::~CXcapCacheSession()
+    {
+    delete iFileManager;
+    //Reduce number of active clients within server
+    if( iCacheServer )
+        iCacheServer->DropSession();
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::ServiceL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::ServiceL( const RMessage2& aMessage )
+    {
+    TInt ret = KErrNone;
+    if( Capabilities( aMessage ) )
+        {
+        CheckTempBuffer();
+        TRAPD( err, DispatchMessageL( aMessage ) );
+        if( err != KErrNone )
+            ret = err;
+        }
+    else ret = KErrPermissionDenied;
+    aMessage.Complete( ret );
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "** Message completed - Error: %d" ), ret );
+    #endif
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::Capabilities
+// 
+// ----------------------------------------------------------
+//
+TBool CXcapCacheSession::Capabilities( const RMessage2& aMessage )
+    {
+    return aMessage.HasCapability( ECapabilityReadUserData ) &&
+           aMessage.HasCapability( ECapabilityWriteUserData );
+    }
+    
+// ----------------------------------------------------------
+// CXcapCacheSession::CheckTempBuffer
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::CheckTempBuffer()
+    {
+    if( iTempBuffer )
+        {
+        delete iTempBuffer;
+        iTempBuffer = NULL;
+        }
+    }
+    
+// ----------------------------------------------------------
+// CXcapCacheSession::CXcapCacheSession
+// 
+// ----------------------------------------------------------
+//
+CXcapCacheSession::CXcapCacheSession( CXcapCacheServer* aServer ) :
+                                      iCacheServer( aServer ),
+                                      iCacheIndex( *CXcapCacheServer::Index() ),
+                                      iCacheIndexAdmin( *CXcapCacheServer::IndexAdmin() )
+    {
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::ConstructL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::ConstructL()
+    {
+    iCacheServer->AddSession();
+    iFileManager = CFileMan::NewL( iCacheServer->FileSession() );
+    #ifdef _DEBUG
+        TInt count = 0;
+        iCacheServer->CacheSize( count );
+    #endif
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::PanicClient
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::PanicClient( TInt aPanic )
+    {
+    _LIT( KTxtSessionPanic,"Test Server Session panic");
+    User::Panic( KTxtSessionPanic, aPanic );
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::DispatchMessageL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::DispatchMessageL( const RMessage2& aMessage )
+    {
+    switch( aMessage.Function() )
+        {
+        case EXcapCacheFetchInfo:
+            FetchDocumentInfoL( aMessage );
+            break;
+        case EXcapCacheFetchData:
+            FetchDocumentContentsL( aMessage );
+            break;
+        case EXcapCacheStore:
+            {
+            TInt entryCount = 0;
+            CacheXcapDataL( aMessage );
+            TInt size = iCacheServer->CacheSize( entryCount );
+            CheckUnindexedEntriesL( entryCount );
+            //Recheck the size
+            size = iCacheServer->CacheSize( entryCount );
+            const TInt maxSize = iCacheServer->MaxCacheSize();
+            //If there's only one document filling the
+            //whole data area, there's not much to be done
+            //NOTE: Index & pagefile are always there => 3
+            if( size >= maxSize && entryCount > 3 )
+                {
+                #ifdef _DEBUG
+                    CXcapCacheServer::WriteToLog( _L8( " Cache too large: %d bytes" ), size );
+                #endif
+                iCacheIndex.SortEntriesL();
+                const TInt compression( iCacheServer->MaxCacheSize() * KDefaultCompression );
+                //NOTE: Index & pagefile are always there -> 3
+                TBool ready = EFalse;
+                while( entryCount > 3 && size > compression && !ready )
+                    {
+                    //The entries have been sorted => FIFO
+                    CXcapCacheIndexEntry* entry = iCacheIndex.Entry( 0 );
+                    if( entry )
+                    	{
+                        DeleteFromStorageL( entry->FileName16L() );
+                        iCacheIndex.RemoveEntry( 0 );
+                        iCacheIndexAdmin.RemoveTableIndex( 0 );
+                        FlushCacheDataL();
+                        size = iCacheServer->CacheSize( entryCount );
+                    	}
+                    else ready = ETrue;
+                    }
+                } 
+            }  
+            break;
+        case EXcapCacheDelete:
+            DeleteCacheDataL( aMessage );
+            break;
+        case EXcapCacheCheckValidity:
+            CheckValidityL( aMessage );
+            break;
+        case EXcapCacheFlush:
+            FlushCacheDataL();
+            break;
+        default:
+            PanicClient( EBadRequest );
+        }
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::CheckUnindexedEntriesL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::CheckUnindexedEntriesL( TInt aTotalCount )
+    {
+    #ifdef _DEBUG
+    	CXcapCacheServer::WriteToLog( _L8( "CXcapCacheSession::CheckUnindexedEntriesL()" ) );
+        CXcapCacheServer::WriteToLog( _L8( "  Total count: %d" ), aTotalCount );
+	#endif
+    const TInt indexed = iCacheIndex.EntryCount();
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "  Indexed entries: %d" ), indexed );
+	#endif
+    if( aTotalCount > indexed + 2 )  //index + pagefile = 2
+        {
+        CDesC16ArraySeg* array = new ( ELeave ) CDesC16ArraySeg( indexed );
+        CleanupStack::PushL( array );
+        array->AppendL( KCacheServerIndexF() );
+        array->AppendL( KCacheServerPageFileF() );
+        for( TInt i = 0;i < indexed;i++ )
+            {
+            const TChar delimiter = 92;
+            TPtrC temp( iCacheIndex.Entry( i )->FileName16L() );
+            TPtrC entry( temp.Right( temp.LocateReverse( delimiter ) + 1 ) );
+            array->AppendL( entry );
+            }
+        DeleteExcessL( *array );
+        array->Reset();
+        CleanupStack::PopAndDestroy();  //array
+        }
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::DeleteExcessL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::DeleteExcessL( const MDesC16Array& aIndexedEntries )
+	{
+	#ifdef _DEBUG
+    	CXcapCacheServer::WriteToLog( _L8( "CXcapCacheSession::DeleteExcessL()" ) );
+	#endif
+    CDir* directory = NULL;
+    RFs& session = CXcapCacheServer::FileSession();
+    User::LeaveIfError( session.GetDir( KCacheServerRoot, KEntryAttNormal,
+    					ESortNone, directory ) );
+    CleanupStack::PushL( directory );
+    const TInt count = directory->Count();
+    for( TInt i = 0;i < count;i++ )
+    	{
+    	TPtrC targetName( ( *directory )[i].iName );
+    	if( !IsIndexed( aIndexedEntries, targetName ) )
+    		{
+        	HBufC* fileName = HBufC::NewLC( targetName.Length() + 
+    						  KCacheServerRoot().Length() );
+    		fileName->Des().Copy( KCacheServerRoot );
+    		fileName->Des().Append( targetName );
+    		TPtrC name( fileName->Des() );
+    		User::LeaveIfError( iFileManager->Delete( name ) );
+    		CleanupStack::PopAndDestroy();  //fileName
+    		}
+    	}
+    CleanupStack::PopAndDestroy();  //directory
+	}
+
+// ----------------------------------------------------------
+// CXcapCacheSession::IsIndexed
+// 
+// ----------------------------------------------------------
+//
+TBool CXcapCacheSession::IsIndexed( const MDesC16Array& aIndexedEntries, const TDesC& aFileName )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "CXcapCacheSession::IsIndexed()" ) );
+    #endif
+    TBool indexed = EFalse;
+    const TInt count = aIndexedEntries.MdcaCount();
+    for( TInt i = 0;!indexed && i < count;i++ )
+    	{
+    	if( aIndexedEntries.MdcaPoint( i ).Compare( aFileName ) == 0 )
+    		{
+    		indexed = ETrue;
+    		}
+    	}
+    return indexed;
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::ReadMsgParamLC
+// 
+// ----------------------------------------------------------
+//
+HBufC* CXcapCacheSession::ReadMsgParam16LC( TInt aMsgIndex, const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "CXcapCacheServer::ReadMsgParam16LC()" ) );
+    #endif
+    TInt length = aMessage.GetDesLength( aMsgIndex );
+    HBufC* buffer = HBufC::NewLC( length );
+    TPtr descriptor( buffer->Des() );
+    aMessage.ReadL( aMsgIndex, descriptor );
+    return buffer;
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::ReadMsgParam8LC
+// 
+// ----------------------------------------------------------
+//
+HBufC8* CXcapCacheSession::ReadMsgParam8LC( TInt aMsgIndex, const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "CXcapCacheServer::ReadMsgParam8LC()" ) );
+    #endif
+    TInt length = aMessage.GetDesLength( aMsgIndex );
+    HBufC8* buffer = HBufC8::NewLC( length );
+    TPtr8 descriptor( buffer->Des() );
+    aMessage.ReadL( aMsgIndex, descriptor );
+    return buffer;
+    }
+       
+// ----------------------------------------------------------
+// CXcapCacheSession::CheckValidityL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::CheckValidityL( const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "** CXcapCacheServer::CheckValidityL()" ) );
+    #endif
+    TPtrC8 etag( ReadMsgParam8LC( 0, aMessage )->Des() );
+    TPtrC name( ReadMsgParam16LC( 1, aMessage )->Des() );
+    TPtrC8 root( ReadMsgParam8LC( 2, aMessage )->Des() );
+    TInt tableIndex = KErrNotFound;
+    CXcapCacheIndexTableEntry* tableEntry = iCacheIndexAdmin.FindL( tableIndex, root, name );
+    if( tableEntry != NULL )
+        {
+        CXcapCacheIndexEntry* entry = iCacheIndex.Entry( tableEntry->Index() );
+        User::Leave( entry->ETag().Compare( etag ) == 0 ? KErrNone : KErrGeneral );
+        }
+    else User::Leave( KErrNotFound );
+    CleanupStack::PopAndDestroy( 3 );  //root, name, etag
+    }
+    
+// ----------------------------------------------------------
+// CXcapCacheSession::DeleteCacheDataL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::DeleteCacheDataL( const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "** CXcapCacheServer::DeleteCacheDataL()" ) );
+    #endif
+    TCacheEntryInfo header;
+    TPckg<TCacheEntryInfo> pack( header );
+    aMessage.ReadL( 0, pack );
+    TInt tableIndex = KErrNotFound;
+    CXcapCacheIndexTableEntry* tableEntry =
+        iCacheIndexAdmin.FindL( tableIndex, *header.iRootUri, *header.iDocumentUri );
+    if( tableEntry )
+        {
+        TInt error = KErrNone;
+        TInt index( tableEntry->Index() );
+        CXcapCacheIndexEntry* entry = iCacheIndex.Entry( index );
+        error = DeleteFromStorageL( entry->FileName16L() );
+        #ifdef _DEBUG
+            CXcapCacheServer::WriteToLog(
+                    _L8( "CXcapCacheSession::DeleteCacheDataL() - error: %d"), error  );
+        #endif
+        iCacheIndex.RemoveEntry( index );
+        iCacheIndexAdmin.RemoveTableIndex( tableIndex );
+        FlushCacheDataL();
+        }
+    else User::Leave( KErrNotFound );
+    }
+    
+// ----------------------------------------------------------
+// CXcapCacheSession::FetchDocumentInfoL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::FetchDocumentInfoL( const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "** CXcapCacheServer::FetchDocumentInfoL()" ) );
+    #endif
+    TInt error = KErrNone;
+    //Read info header
+    TCacheEntryInfo header;
+    TPckg<TCacheEntryInfo> pack( header );
+    aMessage.ReadL( 0, pack );
+    TPtrC name( ReadMsgParam16LC( 2, aMessage )->Des() );
+    TPtrC8 root( ReadMsgParam8LC( 3, aMessage )->Des() );
+    TInt tableIndex = KErrNotFound;
+    #ifdef _DEBUG
+        HBufC8* temp = HBufC8::NewLC( name.Length() );
+        TPtr8 tempDesc( temp->Des() );
+        tempDesc.Copy( name );
+        CXcapCacheServer::WriteToLog( _L8( "   Root:     %S" ), &root );
+        CXcapCacheServer::WriteToLog( _L8( "   Document: %S" ), &tempDesc );
+        CleanupStack::PopAndDestroy();  //temp
+    #endif
+    CXcapCacheIndexTableEntry* tableEntry = iCacheIndexAdmin.FindL( tableIndex, root, name );
+    if( tableEntry != NULL )
+        {
+        TInt index = tableEntry->Index();
+        CXcapCacheIndexEntry* entry = iCacheIndex.Entry( index );
+        TPtrC8 eTag = entry->ETag();
+        header.iDataLength = entry->XmlSize();
+        header.iLastAccess = entry->LastAccess();
+        header.iLastUpdate = entry->LastModified();
+        TPckgC<TCacheEntryInfo> package( header );
+        TRAP( error, aMessage.WriteL( 0, package ) );
+        #ifdef _DEBUG
+            CXcapCacheServer::WriteToLog( _L8( "  Write header: %d" ), error );
+        #endif
+        TRAP( error, aMessage.WriteL( 1, eTag ) );
+        #ifdef _DEBUG
+            CXcapCacheServer::WriteToLog( _L8( "  Write ETag:   %d" ), error );
+        #endif
+        }
+    else User::Leave( KErrNotFound );
+    CleanupStack::PopAndDestroy( 2 );  //root, name
+    }
+    
+// ----------------------------------------------------------
+// CXcapCacheSession::FetchDocumentContentsL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::FetchDocumentContentsL( const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "** CXcapCacheServer::FetchDocumentContentsL()" ) );
+    #endif
+    TPtrC name( ReadMsgParam16LC( 0, aMessage )->Des() );
+    TPtrC8 root( ReadMsgParam8LC( 1, aMessage )->Des() );
+    #ifdef _DEBUG
+        HBufC8* document = HBufC8::NewLC( name.Length() );
+        TPtr8 docDesc( document->Des() );
+        docDesc.Copy( name );
+        CXcapCacheServer::WriteToLog( _L8( "  Document:    %S" ), &docDesc );
+        CXcapCacheServer::WriteToLog( _L8( "  Root URI:    %S" ), &root );
+        CleanupStack::PopAndDestroy();  //document
+    #endif
+    TInt tableIndex = KErrNotFound;
+    CXcapCacheIndexTableEntry* tableEntry = iCacheIndexAdmin.FindL( tableIndex, root, name );
+    if( tableEntry != NULL )
+        {
+        CXcapCacheIndexEntry* entry = iCacheIndex.Entry( tableEntry->Index() );
+        iTempBuffer = ReadFromStorageL( entry->FileName16L() );
+        TPtrC8 dataDesc = iTempBuffer->Des();
+        aMessage.Write( 2, dataDesc );
+        }
+    else User::Leave( KErrNotFound );
+    CleanupStack::PopAndDestroy( 2 );  //name, root
+    }
+    
+// ----------------------------------------------------------
+// CXcapCacheSession::CacheXcapData
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::CacheXcapDataL( const RMessage2& aMessage )
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "** CXcapCacheServer::CacheXcapDataL()" ) );
+    #endif
+    TPtrC doc( ReadMsgParam16LC( 0, aMessage )->Des() );
+    TPtrC8 root( ReadMsgParam8LC( 1, aMessage )->Des() );
+    TPtrC8 etag( ReadMsgParam8LC( 2, aMessage )->Des() );
+    TPtrC8 data( ReadMsgParam8LC( 3, aMessage )->Des() );
+    #ifdef _DEBUG
+        HBufC8* document = HBufC8::NewLC( doc.Length() );
+        TPtr8 docDesc( document->Des() );
+        docDesc.Copy( doc );
+        CXcapCacheServer::WriteToLog( _L8( "  Document:    %S" ), &docDesc );
+        CXcapCacheServer::WriteToLog( _L8( "  ETag:        %S" ), &etag );
+        CXcapCacheServer::WriteToLog( _L8( "  Root URI:    %S" ), &root );
+        CXcapCacheServer::WriteToLog( _L8( "  Data:        %d bytes" ), data.Length() );
+        CleanupStack::PopAndDestroy();  //document
+    #endif
+    TInt tableIndex = KErrNotFound;
+    TCacheEntryInfo header;
+    header.iEtag = &etag;
+    header.iRootUri = &root;
+    header.iRespData = &data;
+    header.iDocumentUri = &doc;
+    header.iDataLength = data.Length();
+    CXcapCacheIndexTableEntry* tableEntry = iCacheIndexAdmin.FindL( tableIndex, root, doc );
+    CXcapCacheIndexEntry* entry = NULL;
+    if( tableEntry != NULL )
+        {
+        entry = iCacheIndex.Entry( tableEntry->Index() );
+        entry->UpdateEntryL( &header );
+        }
+    else
+        {
+        entry = CXcapCacheIndexEntry::NewL( &header );
+        CleanupStack::PushL( entry );
+        TInt index = iCacheIndex.UpdateIndexL( entry );
+        CleanupStack::Pop();  //entry
+        iCacheIndexAdmin.UpdateIndexTableL( index, &header );
+        }
+    CleanupStack::PopAndDestroy( 4 );  //data, etag, root, name
+    FlushCacheDataL();
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::FlushCacheDataL
+// 
+// ----------------------------------------------------------
+//
+void CXcapCacheSession::FlushCacheDataL()
+    {
+    #ifdef _DEBUG
+        CXcapCacheServer::WriteToLog( _L8( "CXcapCacheServer::FlushCacheDataL()" ) );
+    #endif
+    iCacheIndex.StoreCacheDataL();
+    iCacheIndexAdmin.StoreIndexTableL();
+    }
+
+// ----------------------------------------------------------
+// CXcapCacheSession::DeleteFromStorageL
+// 
+// ----------------------------------------------------------
+//
+TInt CXcapCacheSession::DeleteFromStorageL( const TDesC& aFileName )
+    {
+    #ifdef _DEBUG
+        HBufC8* name = HBufC8::NewLC( aFileName.Length() );
+        TPtr8 nameDesc( name->Des() );
+        nameDesc.Copy( aFileName );
+        CXcapCacheServer::WriteToLog( _L8( "CXcapCacheServer::DeleteFromStorageL() - Filename: %S" ), &nameDesc );
+        CleanupStack::PopAndDestroy();  //name
+    #endif
+    TInt error = iFileManager->Delete( aFileName );
+    return error;
+    }
+            
+// ----------------------------------------------------------
+// CXcapCacheSession::FlushCacheDataL
+// 
+// ----------------------------------------------------------
+//
+HBufC8* CXcapCacheSession::ReadFromStorageL( const TDesC& aFileName )
+    {
+    #ifdef _DEBUG
+        HBufC8* name = HBufC8::NewLC( aFileName.Length() );
+        TPtr8 nameDesc( name->Des() );
+        nameDesc.Copy( aFileName );
+        CXcapCacheServer::WriteToLog( _L8( "CXcapCacheServer::ReadFromStorageL() - Filename: %S" ), &nameDesc );
+        CleanupStack::PopAndDestroy();  //name
+    #endif
+    RFile file;
+    HBufC8* data = NULL;
+    User::LeaveIfError( file.Open( CXcapCacheServer::FileSession(), aFileName, EFileRead ) );
+    CleanupClosePushL( file );
+    TInt size = 0;
+    User::LeaveIfError( file.Size( size ) );
+    data = HBufC8::NewL( size );
+    TPtr8 pointer( data->Des() );
+    file.Read( pointer );
+    CleanupStack::PopAndDestroy();  //file
+    return data;
+    }
+
+
+
+
+
+