--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/PECengine/StorageManager2/ServerSrc/CPEngStorageServer.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1256 @@
+/*
+* Copyright (c) 2002 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: Implementation of class CPEngStorageServer
+*
+*/
+
+
+// Include Files
+#include <e32svr.h>
+#include <badesca.h>
+#include <s32mem.h>
+
+
+#include "CPEngStorageServer.h"
+#include "CPEngStorageSession.h"
+#include "CPEngStorageFolder.h"
+#include "PEngStorageServerCommon.h"
+#include "TPEngServerParams.h"
+#include "CPEngHandlerListenEvents.h"
+#include "PEngInternalGlobalConsts.h"
+#include "CPEngTimer.h"
+#include "CPEngActiveScheduler.h"
+
+// Session Slot utility
+#include "CPEngSessionSlotId.h"
+#include "CPEngSessionSlotState.h"
+#include "CPEngSessionSlotEvent.h"
+#include "RObjectArray.h"
+
+// Hash Tool
+#include "PEngHashTool.h"
+
+// Debug Prints
+#include "PresenceDebugPrint.h"
+
+
+// CONSTANTS
+
+// Init size of the buffer for client server communications
+static const TInt KBufferInitSize = 100;
+
+// Static data for Capability check configuration
+static const TInt KPEngStoreServRangeCount = 2;
+
+/**
+ * Ranges for the Request values
+ * All requests will fall in one range
+ */
+static const TInt PEngStoreServRanges[ KPEngStoreServRangeCount ] =
+ {
+ // Range from EMainSessShutdownServer to EFolderSubSessNotifyChangedSIDs
+ 0,
+
+ // range is from EHighestStoreServerRequest request to KMaxInt
+ EHighestStoreServerRequest
+ };
+
+/**
+ * Element indexes for the defined ranges
+ * we have only one range and for it is defined only one Element
+ */
+static const TUint8 KPEngStoreServElementsIndex[ KPEngStoreServRangeCount ] =
+ {
+ // First element in the element array will be applied for this range
+ 0,
+ // Not supported will be applied for this range
+ CPolicyServer::ENotSupported
+ };
+
+// Policy elements
+static const CPolicyServer::TPolicyElement KPEngStoreServElements[] =
+ {
+ {
+ _INIT_SECURITY_POLICY_C2( ECapabilityReadUserData,
+ ECapabilityWriteUserData ),
+ CPolicyServer::EFailClient
+ }
+ };
+
+static const CPolicyServer::TPolicy KPEngServerPolicy =
+ {
+ // The index into Elements,that is used to check a connection attempt
+
+ 0,
+
+ // Number of ranges in the iRanges array
+ KPEngStoreServRangeCount,
+
+ // A pointer to an array of ordered ranges of request numbers
+ PEngStoreServRanges,
+
+ // A pointer to an array of TUint8 values specifying
+ // the appropriate action to take for each range in iRanges
+ KPEngStoreServElementsIndex,
+
+ // A pointer to an array of distinct policy elements
+ KPEngStoreServElements
+ };
+
+// MACROS
+#define RETURN_IF_ERROR( aError )\
+ if( aError != KErrNone )\
+ {\
+ return aError;\
+ }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::CPEngStorageServer
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CPEngStorageServer::CPEngStorageServer( TInt aPriority )
+ : CPolicyServer( aPriority, KPEngServerPolicy ),
+ iRunning( EFalse )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::ConstructL()
+ {
+ StartL( KStorageServerName );
+ iBuff16.CreateL( KBufferInitSize );
+ iBuff8.CreateL( KBufferInitSize );
+ // create container collection
+ iContainerIx = CObjectConIx::NewL();
+ iSubSessionCnt = iContainerIx->CreateL();
+ iFoldersCnt = iContainerIx->CreateL();
+ iObserversCnt = iContainerIx->CreateL();
+
+ // set up file system enviroment
+ User::LeaveIfError( iFs.Connect() );// connect to file server
+ // set session to the private folder
+ TInt err( iFs.CreatePrivatePath( EDriveC ) );
+ if ( err != KErrAlreadyExists )
+ {
+ User::LeaveIfError( err );
+ }
+ User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) );
+ TFileName name;
+ iFs.SessionPath( name );
+ name.Append( KPEngStorageTempFolder );
+ iTempFolder = name.AllocL();
+
+ // make sure we have Storage folder, flush it first and then created
+ CFileMan* fileMan = CFileMan::NewL( iFs );
+ CleanupStack::PushL( fileMan );
+ fileMan->RmDir( *iTempFolder );
+ // ignore errors
+ iFs.Delete( *iTempFolder );
+ CleanupStack::PopAndDestroy(); // fileMan
+ // try to create temp folder
+ TInt er ( iFs.MkDirAll( *iTempFolder ) );
+ if ( er != KErrAlreadyExists )
+ {
+ User::LeaveIfError( er );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPEngStorageServer* CPEngStorageServer::NewL( TInt aPriority )
+ {
+ CPEngStorageServer* self = CPEngStorageServer::NewLC( aPriority );
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPEngStorageServer* CPEngStorageServer::NewLC( TInt aPriority )
+ {
+ CPEngStorageServer* self = new( ELeave ) CPEngStorageServer( aPriority );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// Destructor (virtual by CBase)
+CPEngStorageServer::~CPEngStorageServer()
+ {
+ // clean all containers from the objects in it
+ // close all elements of the array
+ if ( iFoldersCnt )
+ {
+ for ( TInt x( iFoldersCnt->Count() - 1 ) ; x >= 0 ; --x )
+ {
+ ( *iFoldersCnt )[ x ]->Close();
+ }
+ }
+
+
+ // close all elements of the array
+ if ( iObserversCnt )
+ {
+ for ( TInt y( iObserversCnt->Count() - 1 ) ; y >= 0 ; --y )
+ {
+ ( *iObserversCnt )[ y ]->Close();
+ }
+ }
+
+ // all containers are deleted with the collection
+ delete iContainerIx;
+ // clean file enviroment
+ iFs.Close();
+ delete iTempFolder;
+ // shut down plugin server
+ delete iTimeOut;
+ iBuff16.Close();
+ iBuff8.Close();
+ }
+
+
+// =============================================================================
+// =============== Functions from base class ===================================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::ExecuteServerL()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngStorageServer::ExecuteServerL( TPEngServerParams& aParams )
+ {
+ //Renaming must be done as early as possible
+ aParams.RenameMainThread( KStorageServerName );
+
+ TInt res( KErrNone );
+
+ // start scheduler and server
+ CPEngActiveScheduler* pA = new( ELeave )CPEngActiveScheduler;
+ CleanupStack::PushL( pA );
+ CPEngActiveScheduler::Install( pA );
+
+ //If exe server, call RunServerL directly.
+ TRAP( res, RunServerL( aParams ) );
+
+ CPEngActiveScheduler::Install( NULL );
+ CleanupStack::PopAndDestroy();//pA
+ return res;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::StopServer()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::StopServer()
+ {
+ if ( iRunning )
+ {
+ CPEngActiveScheduler::Stop();
+ }
+ iRunning = EFalse;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::RunServerL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::RunServerL( TPEngServerParams& aParams )
+ {
+ PENG_DP( D_PENG_LIT( "CPEngStorageServer::RunServerL()" ) );
+
+ //One instance of server must be allocated here.
+ CPEngStorageServer* server = CPEngStorageServer::NewLC( KServerPriority );
+
+ //must die if can't signal client
+ aParams.Signal();
+ // start fielding requests from clients
+ //Thread is ended when CPEngActiveScheduler::Stop is called.
+ server->StartServer();
+
+
+ CleanupStack::PopAndDestroy();//server
+ // finished
+ }
+
+
+// =============================================================================
+// =============== Functions from the MPEngStorageServer class =================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::AddSubSessionL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::AddSubSessionL(
+ CObject& aSubSession )
+ {
+ iSubSessionCnt->AddL( &aSubSession );
+ }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::RemoveSubSessionL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::RemoveSubSessionL(
+ CObject& aSubSession )
+ {
+ iSubSessionCnt->Remove( & aSubSession );
+ }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::RegisterGlobEventListenerL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::RegisterGlobEventListenerL(
+ const RPEngMessage& /* aMessage */,
+ TUint32 aSessionId )
+ {
+ CPEngHandlerListenEvents* reqHandler = FindRequestHandler( aSessionId ,
+ EMainSessListenGlobalEvents );
+ if ( reqHandler )
+ {
+ // this handler already exists, not allowed by multiple
+ User::Leave( KErrAlreadyExists );
+ }
+ // create new handler
+ reqHandler = CPEngHandlerListenEvents::NewLC( aSessionId );
+ iObserversCnt->AddL( reqHandler );
+ CleanupStack::Pop(); // newHandler
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::CancelRequestL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::CancelRequestL(
+ const RPEngMessage& aMessage,
+ TUint32 aSessionId )
+ {
+ CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId,
+ static_cast<TPEngStorageServerMessages> ( aMessage.Int0() ) );
+ // ignore if such a request does not exists
+ if ( reqHandler )
+ {
+ reqHandler->CancelRequestD();
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::CancelRequestL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::CancelAllSessionRequests(
+ TUint32 aSessionId )
+ {
+ for ( TInt x( iObserversCnt->Count() - 1 ) ; x >= 0 ; --x )
+ {
+ CPEngRequestHandler* handler = static_cast<CPEngRequestHandler*>( ( *iObserversCnt )[ x ] );
+ if ( handler->SessionId() == aSessionId )
+ {
+ handler->CancelRequestD();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::ReloadAsynchronousScoutL()
+// Reload Asynchronous scout of the async observer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::ReloadAsynchronousScoutL(
+ const RPEngMessage& aMessage,
+ TUint32 aSessionId )
+ {
+ CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId,
+ static_cast<TPEngStorageServerMessages> ( aMessage.Int0() ) );
+ if ( !reqHandler )
+ {
+ // there is not such a request to be reloaded
+ User::Leave( KErrArgument );
+ }
+ reqHandler->ReloadScoutWithNewMessageL( aMessage );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::CreateSessionFolderL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::CreateSessionFolderL(
+ const RPEngMessage& aMessage )
+ {
+ CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage );
+ CPEngSessionSlotState* state = NULL;
+ CPEngStorageFolder* folder = NULL;
+ HBufC* stateFile = NULL;
+ // load state
+ TInt cleanUp ( LoadSessionStateLCX( *sessId, ETrue,
+ state, folder, stateFile ) );
+
+ // update state with the new application ID
+ aMessage.ReadOneDescriptorL( KMessageSlot1, iBuff16 );
+
+ // also create session slot global event for notification
+ CPEngSessionSlotEvent* globEvent = PackGlobEventLC( *state,
+ EPEngEventNWSessionSlotCreated,
+ iBuff16 );
+
+ TPtr stateFileName( stateFile->Des() );
+ UpdateSessionSltStateL( folder, *state, *globEvent, stateFileName );
+
+ // notify about event
+ globEvent->PackEventL( iBuff8 );
+ NotifyGlobalEvent( iBuff8 );
+
+ // clean globEvent, (state), stateFile, sessId
+ CleanupStack::PopAndDestroy( 2 + cleanUp );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::RemoveSessionFolderL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::RemoveSessionFolderL(
+ const RPEngMessage& aMessage )
+ {
+ CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage );
+ CPEngSessionSlotState* state = NULL;
+ CPEngStorageFolder* folder = NULL;
+ HBufC* stateFile = NULL;
+ // load state
+ TInt cleanUp ( LoadSessionStateLCX( *sessId,
+ EFalse,
+ state,
+ folder,
+ stateFile ) );
+
+ if ( folder )
+ {
+ // folder is active, refuse any deletion
+ User::Leave( KErrInUse );
+ }
+ // remove registered ID from the session
+ aMessage.ReadOneDescriptorL( KMessageSlot1, iBuff16 );
+
+ // also create session slot global event for notification
+ CPEngSessionSlotEvent* globEvent = PackGlobEventLC(
+ *state,
+ EPEngEventNWSessionSlotRemoved,
+ iBuff16 );
+
+ TPtr stateFileName( stateFile->Des() );
+ UpdateSessionSltStateL( folder, *state, *globEvent, stateFileName );
+
+ // notify about event
+ globEvent->PackEventL( iBuff8 );
+ NotifyGlobalEvent( iBuff8 );
+
+ // clean globEvent, (state), stateFile, sessId
+ CleanupStack::PopAndDestroy( 2 + cleanUp );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::SessionStateL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::SessionStateL(
+ const RPEngMessage& aMessage )
+ {
+ CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage );
+ CPEngStorageFolder* folder = FindStorageFolder( *sessId );
+ CPEngSessionSlotState* state = NULL;
+ if ( folder )
+ {
+ state = &( folder->SessionSlotState() );
+ }
+ else
+ {
+ HBufC* stateFile = NULL;
+ state = ReadSessionStatePermanentLC( *sessId, stateFile );
+ }
+
+ state->PackDataL( EPureState, iBuff8 );
+
+ TInt err( aMessage.WriteOneDescriptor( KMessageSlot1, iBuff8 ) );
+ if ( err == KErrOverflow )
+ {
+ User::Leave( iBuff8.Length() );
+ }
+ User::LeaveIfError( err );
+
+ if ( !folder )
+ {
+ CleanupStack::PopAndDestroy( 2 ); // state, stateFile
+ }
+ CleanupStack::PopAndDestroy(); // sessId
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::AllSessionStatesL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::AllSessionStatesL(
+ const RPEngMessage& aMessage )
+ {
+ // pack all states to one big buffer
+ // this takes all active folders and adds sessions not active
+ CDir* dirList = NULL;
+ TFileName dir;
+ User::LeaveIfError( iFs.PrivatePath( dir ) );
+ // insert drive leter on the beginning
+ dir.Insert( 0, KPEngStorageDrive );
+
+ User::LeaveIfError( iFs.GetDir( dir,
+ KEntryAttNormal,
+ ESortByName,
+ dirList ) );
+ CleanupStack::PushL( dirList );
+ TInt count( dirList->Count() );
+ RObjectArray<CPEngSessionSlotState> states;
+ CleanupClosePushL( states );
+ // 4 for the count of the states
+ TInt size( 4 );
+ for ( TInt x( 0 ) ; x < count ; x++ )
+ {
+ const TEntry& entry = ( *dirList )[ x ];
+ if ( ! entry.IsDir() )
+ {
+ CPEngSessionSlotState* state = CPEngSessionSlotState::NewLC();
+ ReadFileL( entry.iName, iBuff8 );
+ state->UnpackDataL( iBuff8, EPermanentData );
+ states.AppendL( state );
+ size += state->Size( EPermanentData );
+ CleanupStack::Pop(); // state
+ }
+ }
+ // now go through all session and if they are loaded as folders
+ // and pack them to the buffer
+ // get buffer for transfer
+ CBufFlat* buf = CBufFlat::NewL( size );
+ CleanupStack::PushL( buf );
+ RBufWriteStream ws;
+ CleanupClosePushL( ws );
+ ws.Open( *buf ); // CSI: 65 #
+
+ // write count of all sessions
+ count = states.Count();
+ ws.WriteInt32L( count );
+
+ for ( TInt i( 0 ) ; i < count ; i++ )
+ {
+ CPEngStorageFolder* folder = FindStorageFolder(
+ states[ i ]->SessionSlotId() );
+ if ( folder )
+ {
+ // there is loaded folder, take state from there
+ folder->SessionSlotState().ExternalizeL( ws, EWholeState );
+ }
+ else
+ {
+ states[ i ]->ExternalizeL( ws, EWholeState );
+ }
+ }
+ // write data to the client side
+ TInt err( aMessage.WriteOneDescriptor( KMessageSlot0, buf->Ptr( 0 ) ) );
+ if ( err == KErrOverflow )
+ {
+ User::Leave( buf->Ptr( 0 ).Length() );
+ }
+ User::LeaveIfError( err );
+ CleanupStack::PopAndDestroy( 4 ); // ws, buf, states, dirList,
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::StorageFolderL()
+// -----------------------------------------------------------------------------
+//
+CPEngStorageFolder* CPEngStorageServer::StorageFolderL(
+ const RPEngMessage& aMessage )
+ {
+ CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage );
+ CPEngStorageFolder* folder = LoadStorageFolderL( *sessId );
+ CleanupStack::PopAndDestroy(); // sessId
+ return folder;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::NotifyGlobalEvent()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::NotifyGlobalEvent(
+ const TDesC8& aGlobalEvent )
+ {
+ // better to go through array from end
+ for ( TInt x( iObserversCnt->Count() - 1 ) ; x >= 0 ; x-- )
+ {
+ CPEngHandlerListenEvents* handler =
+ static_cast<CPEngHandlerListenEvents*>( ( *iObserversCnt )[ x ] );
+ handler->NotifyEvent( aGlobalEvent );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::NotifyError()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::NotifyError(
+ TInt aError )
+ {
+ // better to go through array from end
+ for ( TInt x( iObserversCnt->Count() - 1 ) ; x >= 0 ; x-- )
+ {
+ CPEngHandlerListenEvents* handler =
+ static_cast<CPEngHandlerListenEvents*>( ( *iObserversCnt )[ x ] );
+ handler->NotifyError( aError );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::IsAppIdRegisteredL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::IsAppIdRegisteredL(
+ const RPEngMessage& aMessage )
+ {
+ CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage );
+ aMessage.ReadOneDescriptorL( KMessageSlot1, iBuff16 );
+
+ CPEngSessionSlotState* state = NULL;
+ CPEngStorageFolder* folder = NULL;
+ HBufC* stateFile = NULL;
+ // load state
+ TInt cleanUp ( LoadSessionStateLCX( *sessId, ETrue,
+ state, folder, stateFile ) );
+ // check if appId is registered
+ state->ApplicationRegisteredL( iBuff16 );
+ // clean (state),stateFile,appId,sessId
+ CleanupStack::PopAndDestroy( cleanUp + 2 );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::BackUpActive()
+// -----------------------------------------------------------------------------
+//
+TBool CPEngStorageServer::BackUpActive()
+ {
+ return iBackUpActive;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::WipeSessionSlotFolderL()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::WipeSessionSlotFolderL(
+ const RPEngMessage& aMessage )
+ {
+ CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage );
+ CPEngSessionSlotState* state = NULL;
+ CPEngStorageFolder* folder = NULL;
+ HBufC* stateFile = NULL;
+ // load state
+ TInt cleanUp ( LoadSessionStateLCX( *sessId,
+ EFalse,
+ state,
+ folder,
+ stateFile ) );
+
+ if ( folder )
+ {
+ // folder is active, refuse any deletion
+ User::Leave( KErrInUse );
+ }
+
+ TPtr stateFileName( stateFile->Des() );
+ User::LeaveIfError( CleanStorageFromSessionL( stateFileName ) );
+
+ // clean globEvent, (state), stateFile, sessId
+ CleanupStack::PopAndDestroy( 1 + cleanUp );
+ }
+
+
+// =============================================================================
+// ======== New function of the CPEngStorageServer =====================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::SessionCreated()
+// Session has been created
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::SessionCreated()
+ {
+ iSessCount++;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::SessionDied()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::SessionDied()
+ {
+ iSessCount--;
+ if ( iSessCount == 0 )
+ {
+ // Start timer
+ delete iTimeOut;
+ iTimeOut = NULL;
+
+ TRAP_IGNORE(
+ {
+ iTimeOut = CPEngTimer::NewL( *this );
+ iTimeOut->After( KServerCloseTimeOut );
+ } );
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::TimeExpired()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::TimeExpired()
+ {
+ if ( iSessCount == 0 )
+ {
+ // stop server
+ StopServer();
+ }
+ }
+
+
+// =============================================================================
+// =============== Functions from the MBackupOperationObserver class ===========
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::HandleBackupOperationEventL()
+// Called when a backup or restore operation either starts or ends.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+// Restore is not implemented before new API won't be delivered
+/*
+void CPEngStorageServer::HandleBackupOperationEventL(
+ const TBackupOperationAttributes& aBackupOperationAttributes)
+ {
+ }
+*/
+// =============================================================================
+// =============== Functions from the CServer2 class ===========================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::NewSessionL()
+// -----------------------------------------------------------------------------
+//
+CSession2* CPEngStorageServer::NewSessionL(
+ const TVersion &aVersion,
+ const RMessage2& /*aMessage*/ ) const
+ {
+ if ( !User::QueryVersionSupported( aVersion, TVersion(
+ KRequiredVersionMajor,
+ KRequiredVersionMinor,
+ KRequiredVersionBuild ) ) )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ return CPEngStorageSession::NewL( const_cast<CPEngStorageServer&>( *this ) );
+ }
+
+
+// =============================================================================
+// =============== New Private methods from class ==============================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::StartServer()
+// Start Server
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::StartServer()
+ {
+ iRunning = ETrue;
+ PENG_DP( D_PENG_LIT( "PECStorageServer::Started" ) );
+ CPEngActiveScheduler::Start();
+ PENG_DP( D_PENG_LIT( "PECStorageServer::Stopped" ) );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::TranslateSessionIdLC()
+// Read Session ID from the client's message
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngSessionSlotId* CPEngStorageServer::TranslateSessionIdLC(
+ const RPEngMessage& aMessage )
+ {
+ // 0 slot of the message has always session identification if required
+ CPEngSessionSlotId* sessId = CPEngSessionSlotId::NewLC();
+
+ aMessage.ReadOneDescriptorL( KMessageSlot0, iBuff8 );
+ sessId->UnPackL( iBuff8 );
+ return sessId;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::FindStorageFolder()
+// Try to find session Folder if it is active
+// if folder is not active, it returns NULL pointer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngStorageFolder* CPEngStorageServer::FindStorageFolder(
+ const CPEngSessionSlotId& aSessionId )
+ {
+ // look for the session
+ TInt count( iFoldersCnt->Count() );
+ for ( TInt x( 0 ) ; x < count ; x++ )
+ {
+ CPEngStorageFolder* folder =
+ static_cast<CPEngStorageFolder*> ( ( *iFoldersCnt )[ x ] );
+ if ( KErrNone == folder->SessionSlotState().SessionSlotId().Match( aSessionId ) )
+ {
+ return folder;
+ }
+ }
+ return NULL;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::LoadStorageFolderL()
+// Load storage folder,
+// there is open handle to the returner pointer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngStorageFolder* CPEngStorageServer::LoadStorageFolderL(
+ const CPEngSessionSlotId& aSessionId )
+ {
+ CPEngStorageFolder* folder = FindStorageFolder( aSessionId );
+ if ( folder )
+ {
+ TInt val = folder->Open(); // CSI: 65 #
+ return folder;
+ }
+
+ // read session state from permanent store
+ HBufC* stateFile = NULL;
+ CPEngSessionSlotState* state = ReadSessionStatePermanentLC( aSessionId,
+ stateFile );
+
+ // it makes directory if does not exists
+ TPtr fileName = stateFile->Des();
+ UpdateFileToFolderName( fileName );
+
+ // create folder class, pass state
+ CPEngStorageFolder* newFolder = CPEngStorageFolder::NewL( iFs,
+ *iTempFolder,
+ iBuff16 );
+ CleanupClosePushL( *newFolder );
+
+ // update Folder path to include, session part
+ TFileName sessPath;
+ User::LeaveIfError( iFs.SessionPath( sessPath ) );
+ stateFile = stateFile->ReAllocL( stateFile->Length() +
+ sessPath.Length() );
+ stateFile->Des().Insert( 0, sessPath );
+
+ CleanupStack::Pop(); //newFolder
+ CleanupStack::Pop( 2 ); // state, stateFile
+
+ // following functions are transfering ownership
+ newFolder->SetSessionSlotState( *state );
+ newFolder->SetSessionFolder( * stateFile );
+
+ // add folder to the folders container
+ CleanupClosePushL( * newFolder );
+ iFoldersCnt->AddL( newFolder );
+ CleanupStack::Pop(); // newFolder
+ return newFolder;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::LoadSessionStateLCX()
+// Load session slot state
+// If there is Storage folder for this session
+// then state is taken from it, while nothing is put on clean up stack
+// if not, then state is loaded from state file,
+// if file does not exist, depends on the aCreate flag, can be
+// created or it leave with KErrNotFound
+// order items on clan up stack is: aStateFileName,
+// or aStateFileName, aSessState
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CPEngStorageServer::LoadSessionStateLCX(
+ CPEngSessionSlotId& aSessId,
+ TBool aCreate,
+ CPEngSessionSlotState*& aSessState,
+ CPEngStorageFolder*& aStorageFolder,
+ HBufC*& aStateFileName )
+ {
+ aStorageFolder = FindStorageFolder( aSessId );
+ // was state folder found or not
+ if ( aStorageFolder )
+ {
+ aSessState = &( aStorageFolder->SessionSlotState() );
+ aStateFileName = PEngHashTool::HashStateNameL( // CSI: 42 #
+ aSessState->SessionSlotId().ServiceAddress(),
+ aSessState->SessionSlotId().UserId() );
+ CleanupStack::PushL( aStateFileName ); // CSI: 42 #
+ return 1;
+ }
+ if ( !aCreate )
+ {
+ aSessState = ReadSessionStatePermanentLC( aSessId, aStateFileName ); // CSI: 42 #
+ return 2;
+ }
+
+ // if it won't exist create it, so we need to trap leave
+ TRAPD( e,
+ {
+ aSessState = ReadSessionStatePermanentLC( aSessId,
+ aStateFileName );
+ // we need to fool TRAP CleanUp level check
+ CleanupStack::Pop( 2 );
+ } );
+
+ // put those elements back to CleanUpStack
+ if ( e == KErrNone )
+ {
+ CleanupStack::PushL( aStateFileName ); // CSI: 42 #
+ CleanupStack::PushL( aSessState ); // CSI: 42 #
+ }
+
+ // does even the file exist?
+ else if ( e == KErrNotFound )
+ {
+ // file does not exists, create state file and folder
+ aStateFileName = PEngHashTool::HashStateNameL( aSessId.ServiceAddress(), // CSI: 42 #
+ aSessId.UserId() );
+ CleanupStack::PushL( aStateFileName ); // CSI: 42 #
+ aSessState = CPEngSessionSlotState::NewLC(); // CSI: 42 #
+ aSessState->SetSessionSlotId( aSessId, EFalse );
+ TPtr fileName = aStateFileName->Des();
+ CreateSessionDirectoryL( fileName ); // CSI: 42 #
+ }
+ else
+ {
+ // was there some other error?
+ User::LeaveIfError( e ); // CSI: 42 #
+ }
+ return 2;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::ReadSessionStatePermanentLC()
+// Read State file from permanent store if it does exists
+// Function returns Session Slot state and des buffer with
+// session slot state file name ownership of both is transfered
+// to the calling client
+// both items are left on clean up stack, while state is topest one
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngSessionSlotState* CPEngStorageServer::ReadSessionStatePermanentLC(
+ const CPEngSessionSlotId& aSessionId,
+ HBufC*& aFileName )
+ {
+ // Folder is not activated yet, check if folder does exist in the store
+ // get folder name of the session
+ aFileName = PEngHashTool::HashStateNameL(
+ aSessionId.ServiceAddress(),
+ aSessionId.UserId() );
+ CleanupStack::PushL( aFileName );
+
+ // try to get state of the session if it exists
+ CPEngSessionSlotState* state = CPEngSessionSlotState::NewLC();
+ ReadFileL( *aFileName, iBuff8 );
+ state->UnpackDataL( iBuff8, EPermanentData );
+ return state;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::UpdateFileToFolderName()
+// Modify State file name to folder name
+// Functions remove state suffix from file name and replaces is with
+// folder delimiter characters
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::UpdateFileToFolderName(
+ TDes& aFileName )
+ {
+ aFileName.SetLength( aFileName.Length() -
+ KPEngStorageStateSuffix().Length() );
+ aFileName.Append( KDirDelim );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::CreateSessionDirectoryL()
+// Create session directory in the file system
+// Passed buffer is used, modified to sued session folder
+// and then back to the state as it was before
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::CreateSessionDirectoryL(
+ TDes& aFileName )
+ {
+ // make directory if does not exists
+ UpdateFileToFolderName( aFileName );
+ TFileName folderName;
+ iFs.SessionPath( folderName );
+ folderName.Append( aFileName );
+ TInt err( iFs.MkDirAll( folderName ) );
+ // ignore KErrAlreadyExist
+ err = ( err == KErrAlreadyExists ? KErrNone : err );
+ User::LeaveIfError( err );
+ // modify folder name back to the state file name
+ aFileName.SetLength( aFileName.Length() - KDirDelimLength );
+ aFileName.Append( KPEngStorageStateSuffix );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::StoreFile()
+// Store data to the file
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CPEngStorageServer::StoreFile(
+ const TDesC& aFileName,
+ const TDesC8& aData )
+ {
+ // open temp file, write date into it and rename it to the correct file
+ RFile temp;
+ TFileName fName;
+ TInt err( temp.Temp( iFs, *iTempFolder, fName, EFileShareExclusive ) );
+ RETURN_IF_ERROR( err );
+ err = temp.Write( aData );
+ if ( ( err != KErrNone ) )
+ {
+ temp.Close();
+ return err;
+ }
+ err = temp.Flush();
+ temp.Close();
+ RETURN_IF_ERROR( err );
+
+ err = iFs.Delete( aFileName );
+ if ( ( err != KErrNone ) && ( err != KErrNotFound ) )
+ {
+ return err;
+ }
+ return iFs.Rename( fName, aFileName );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::ReadFileL()
+// Read data from the file
+// if file does not exists function will leave
+// returned buffer is left on the clean up stack
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::ReadFileL(
+ const TDesC& aFileName,
+ RBuf8& aBuff )
+ {
+ RFile f;
+ User::LeaveIfError( f.Open( iFs, aFileName, EFileRead ) );
+ CleanupClosePushL( f );
+ TInt size( 0 );
+ User::LeaveIfError( f.Size( size ) );
+ if ( size > aBuff.MaxSize() )
+ {
+ aBuff.ReAllocL( size );
+ }
+ aBuff.Zero();
+ User::LeaveIfError( f.Read( aBuff ) );
+ CleanupStack::PopAndDestroy(); // f
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::CleanStorageFromSessionL()
+// Clean storage from session
+// Function deletes session folder and session state
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CPEngStorageServer::CleanStorageFromSessionL( TDes& aFileName )
+ {
+ // delete directory
+ UpdateFileToFolderName( aFileName );
+ TFileName sessionFolder;
+ iFs.SessionPath( sessionFolder );
+ sessionFolder.Append( aFileName );
+
+ CFileMan* fileMan = CFileMan::NewL( iFs );
+ CleanupStack::PushL( fileMan );
+ TInt err( fileMan->RmDir( sessionFolder ) );
+ CleanupStack::PopAndDestroy(); // fileMan
+ RETURN_IF_ERROR( err );
+
+ // modify folder name back to the state file name
+ aFileName.SetLength( aFileName.Length() - KDirDelimLength );
+ aFileName.Append( KPEngStorageStateSuffix );
+
+ // try to delete file
+ return iFs.Delete( aFileName );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::PackGlobEventLC()
+// Create Buffer with global event from the passed
+// state and event enumeration, and application Id
+// Function deletes session folder and session state
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngSessionSlotEvent* CPEngStorageServer::PackGlobEventLC(
+ CPEngSessionSlotState& aState,
+ TPEngNWSessionSlotEvent aEvent,
+ const TDesC& aAppId )
+ {
+ CPEngSessionSlotEvent* newEvent = CPEngSessionSlotEvent::NewLC();
+ newEvent->SetSessionSlotId( &( aState.SessionSlotId() ), EFalse );
+ newEvent->SetAppIdL( aAppId );
+ newEvent->SetSessSltEvent( aEvent );
+ newEvent->SetAppSessSltState( aState.AppState( aAppId ) );
+ newEvent->SetGlobSessSltState( aState.SessionSlotState() );
+ return newEvent;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::UpdateSessionSltStateL()
+// Update Session Slot state
+// Passed session slot folder pointer can be NULL, then
+// session slot state reference is used instead
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageServer::UpdateSessionSltStateL(
+ CPEngStorageFolder* aFolder,
+ CPEngSessionSlotState& aState,
+ CPEngSessionSlotEvent& aEvent,
+ TDes& aFileName )
+ {
+ // do we need to do permanent store update?
+ if ( aState.UpdateStateL( aEvent ) )
+ {
+ // store changes
+ aState.PackDataL( EPermanentData, iBuff8 );
+
+ // open file and store there data
+ TInt e ( StoreFile( aFileName, iBuff8 ) );
+ if ( e != KErrNone )
+ {
+ // remove the ID from the sate, this is for case folder is active
+ aState.RollBackLastUpdate();
+ User::Leave( e );
+ }
+ }
+ aState.CommitLastUpdate();
+ if ( aFolder )
+ {
+ aFolder->CommiteStateUpdate();
+ }
+
+ // shall we clean storage?
+ if ( aState.RegisteredApplications().MdcaCount() == KErrNone )
+ {
+ CleanStorageFromSessionL( aFileName );
+ }
+ }
+
+
+
+// =============================================================================
+// ============= New notification engine functions =============================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageServer::FindRequestHandler()
+// Find Request Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngHandlerListenEvents* CPEngStorageServer::FindRequestHandler(
+ TUint32 aSessionId,
+ TPEngStorageServerMessages aFunction )
+ {
+ TInt count( iObserversCnt->Count() );
+ for ( TInt x( 0 ) ; x < count ; x++ )
+ {
+ CPEngHandlerListenEvents* reqHandler = static_cast<CPEngHandlerListenEvents*>( ( *iObserversCnt )[ x ] );
+ if ( ( reqHandler->SessionId() == aSessionId )
+ && ( reqHandler->RequestFunction() == aFunction ) )
+ {
+ return reqHandler;
+ }
+ }
+ return NULL;
+ }
+
+// End of File