diff -r 000000000000 -r c8caa15ef882 xdmprotocols/XcapProtocol/XcapCache/Server/src/XcapCacheSession.cpp --- /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 +#include +#include +#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 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 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 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; + } + + + + + +