diff -r 95243422089a -r 491b3ed49290 filesystemuis/memscaneng/serversrc/memscanserv.cpp --- a/filesystemuis/memscaneng/serversrc/memscanserv.cpp Thu Aug 19 09:42:45 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,621 +0,0 @@ -/* -* Copyright (c) 2006-2006 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: Memory Scan Server -* -*/ - - - -// SYSTEM INCLUDES -#include -#include // RBufWriteStream - -// USER INCLUDES -#include "memscanserv.h" -#include "memscanutils.h" // traces - - -// --------------------------------------------------------------------------- -// Server startup code -// --------------------------------------------------------------------------- - -// Perform all server initialisation, in particular creation of the -// scheduler and server and then run the scheduler -// -static void RunServerL() - { - // naming the server thread after the server helps to debug panics - User::LeaveIfError(User::RenameThread(KMemScanServName)); - - // create and install the active scheduler we need - CActiveScheduler* scheduler=new(ELeave) CActiveScheduler; - CleanupStack::PushL(scheduler); - CActiveScheduler::Install(scheduler); - // create the server (leave it on the cleanup stack) - CMemScanServ::NewLC(); - // Initialisation complete, now signal the client - - RProcess::Rendezvous(KErrNone); - - // Ready to run - TRACES( RDebug::Print(_L("MemScanServ: server fully running")) ); - CActiveScheduler::Start(); - // Cleanup the server and scheduler - CleanupStack::PopAndDestroy(2, scheduler); - } - -// Server process entry-point -TInt E32Main() - { - __UHEAP_MARK; - TRACES( RDebug::Print(_L("MemScanServ: E32Main")) ); - CTrapCleanup* cleanup=CTrapCleanup::New(); - TInt r=KErrNoMemory; - if (cleanup) - { - TRAP(r,RunServerL()); - delete cleanup; - } - __UHEAP_MARKEND; - return r; - } - -// RMessagePtr2::Panic() also completes the message. This is: -// (a) important for efficient cleanup within the kernel -// (b) a problem if the message is completed a second time -void PanicClient(const RMessagePtr2& aMessage,TMemScanServPanic aPanic) - { - _LIT(KPanic,"MemScanServ"); - aMessage.Panic(KPanic,aPanic); - } - - -// --------------------------------------------------------------------------- -// CShutDown -// --------------------------------------------------------------------------- -inline CShutdown::CShutdown() - :CTimer(-1) - { - CActiveScheduler::Add(this); - } - -inline void CShutdown::ConstructL() - { - CTimer::ConstructL(); - } - -inline void CShutdown::Start() - { - TRACES( RDebug::Print(_L("MemScanServ: starting shutdown timeout")) ); - After(EMemScanServShutdownDelay); - } - -void CShutdown::RunL() - { - TRACES( RDebug::Print(_L("MemScanServ: server timeout ... closing")) ); - CActiveScheduler::Stop(); - } - -// --------------------------------------------------------------------------- -// CMemScanServ -// --------------------------------------------------------------------------- -inline CMemScanServ::CMemScanServ() - :CPolicyServer(0, KMemScanServPolicy, ESharableSessions) - { - } - -CServer2* CMemScanServ::NewLC() - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServ::NewLC")) ); - CMemScanServ* self=new(ELeave) CMemScanServ; - CleanupStack::PushL(self); - self->ConstructL(); - return self; - } - -// 2nd phase construction - ensure the timer and server objects are running -void CMemScanServ::ConstructL() - { - StartL(KMemScanServName); - iShutdown.ConstructL(); - // ensure the server still exits even if the 1st client fails to connect - if( !iShutdown.IsActive() ) - { - iShutdown.Start(); - } - } - - -// Create a new client session. -CSession2* CMemScanServ::NewSessionL(const TVersion& aVersion, const RMessage2&) const - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServ::NewSessionL")) ); - - // Client-Server version check - TVersion version(KMemScanServMajor, KMemScanServMinor, KMemScanServBuild); - if( !User::QueryVersionSupported( version, aVersion ) ) - { - User::Leave( KErrNotSupported ); - } - - return new (ELeave) CMemScanServSession(); - } - -// A new session is being created -// Cancel the shutdown timer if it was running -void CMemScanServ::AddSession() - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServ::AddSession")) ); - ++iSessionCount; - iShutdown.Cancel(); - } - -// A session is being destroyed -// Start the shutdown timer if it is the last session. -void CMemScanServ::DropSession() - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServ::DropSession")) ); - if (--iSessionCount==0) - { - if( !iShutdown.IsActive() ) - { - iShutdown.Start(); - } - } - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession -// --------------------------------------------------------------------------- -inline CMemScanServSession::CMemScanServSession() - { - TRACES( RDebug::Print(_L("MemScanServer: CMemScanServSession::CMemScanServSession")); ) - } - -inline CMemScanServ& CMemScanServSession::Server() - { - return *static_cast(const_cast(CSession2::Server())); - } - -// 2nd phase construct for sessions - called by the CServer framework -void CMemScanServSession::CreateL() - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServSession::CreateL")); ) - Server().AddSession(); - - // Create a transfer buffer - iTransferBuffer = CBufFlat::NewL(KMemScanServTransferBufferExpandSize); - } - -CMemScanServSession::~CMemScanServSession() - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServSession::~CMemScanServSession")); ) - - - delete iTransferBuffer; - delete iMseng; - - - iEventBuffer.Close(); - Server().DropSession(); - } - - -// Handle a client request. -// Leaving is handled by CMemScanServSession::ServiceError() which reports -// the error code to the client -void CMemScanServSession::ServiceL(const RMessage2& aMessage) - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServSession::ServiceL; %d"),aMessage.Function()); ) - switch (aMessage.Function()) - { - case EMemScanPrepareDataGroups: - { - PrepareDataGroupsL( aMessage ); - break; - } - case EMemScanGetDataGroups: - { - GetDataGroupsL( aMessage ); - break; - } - case EMemScanStartScan: - { - MemScanL( aMessage ); - break; - } - case EMemScanPrepareScanResults: - { - PrepareScanResultsL( aMessage ); - break; - } - case EMemScanGetScanResults: - { - GetScanResultsL( aMessage ); - break; - } - case EMemScanRequestScanEvents: - { - RequestScanEventsL( aMessage ); - break; - } - case EMemScanRequestScanEventsCancel: - { - RequestScanEventsCancel( aMessage ); - break; - } - case EMemScanInProgress: - { - ScanInProgress( aMessage ); - break; - } - - default: - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServSession::ServiceL; %d"),aMessage.Function()); ) - PanicClient(aMessage,EPanicIllegalFunction); - break; - } - - } - } - -// Handle an error from CMemScanServSession::ServiceL() -void CMemScanServSession::ServiceError(const RMessage2& aMessage,TInt aError) - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServSession::ServiceError %d"),aError); ) - CSession2::ServiceError(aMessage,aError); - } - - -// *************************************************************************** -// Internal utility functions -// *************************************************************************** - - -// --------------------------------------------------------------------------- -// CMemScanServSession::PrepareDataGroupsL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::PrepareDataGroupsL(const RMessage2& aMessage) - { - // Create scan engine if it does not exist - if(!iMseng) - { - iMseng = CMseng::NewL(*this); - } - - // Get data group name array - CDesCArray* dataGroupArray = iMseng->DataGroupsL(); - CleanupStack::PushL(dataGroupArray); - - - // *** Start externalizing the data group array to transfer buffer - - // Clear the buffer - iTransferBuffer->Reset(); - - // Set buffer for the stream - RBufWriteStream stream(*iTransferBuffer); - CleanupClosePushL(stream); - - // Write number of fields in array to stream - TInt count = dataGroupArray->MdcaCount(); - stream.WriteInt32L(count); - - // Write each field in array to stream - for(TInt i=0; iMdcaPoint(i).Length(); - stream.WriteInt32L(length); // writes datagroup name length to stream - const TPtrC group = dataGroupArray->MdcaPoint(i); - stream << group; // writes one datagroup to stream - } - - stream.CommitL(); - CleanupStack::PopAndDestroy(&stream); - CleanupStack::PopAndDestroy(dataGroupArray); - - // *** externalizing done - - - // Write the size of transfer buffer back to client - TPckgBuf size(iTransferBuffer->Size()); - aMessage.WriteL(0, size); - - // complete the message - aMessage.Complete( KErrNone ); - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::GetDataGroupsL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::GetDataGroupsL(const RMessage2& aMessage) - { - // Get the prepared data groups - aMessage.WriteL( KMesArg0, iTransferBuffer->Ptr(0)); - - aMessage.Complete( KErrNone ); - } - -// --------------------------------------------------------------------------- -// CMemScanServSession::PrepareScanResultsL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::PrepareScanResultsL(const RMessage2& aMessage) - { - // Get scan results from server - CArrayFix* resultArray = iMseng->ScanResultL(); - CleanupStack::PushL(resultArray); - - // *** Start externalizing the result array to transfer buffer - - // Clear the buffer - iTransferBuffer->Reset(); - - // Set buffer for the stream - RBufWriteStream stream(*iTransferBuffer); - CleanupClosePushL(stream); - - // Write number of fields in array to stream - TInt count = resultArray->Count(); - stream.WriteInt32L(count); - - // Write each field in array to stream - for(TInt i=0; iAt(i); - stream << result; // writes one data result to stream - } - - stream.CommitL(); - CleanupStack::PopAndDestroy(&stream); - CleanupStack::PopAndDestroy(resultArray); - - // *** externalizing done - - - // Write the size of transfer buffer back to client - TPckgBuf size(iTransferBuffer->Size()); - aMessage.WriteL(0, size); - - - aMessage.Complete( KErrNone ); - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::GetScanResultsL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::GetScanResultsL(const RMessage2& aMessage) - { - // Get the prepared scan results - aMessage.WriteL( KMesArg0, iTransferBuffer->Ptr(0)); - - aMessage.Complete( KErrNone ); - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::MemScanL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::MemScanL(const RMessage2& aMessage) - { - TRACES( RDebug::Print(_L("MemScanServ: CMemScanServSession::ScanL")); ) - - // Get the first integer parameter of message - TDriveNumber drive = TDriveNumber(aMessage.Int0()); - - iMseng->ScanL( drive ); - aMessage.Complete( KErrNone ); - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::RequestScanEventsL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::RequestScanEventsL(const RMessage2& aMessage) - { - if ( iScanEventMessage.IsNull() ) - { - // We want check that the client hasn't requested scan events - // twice in a row. The client is only allowed to have one - // scan event request outstanding at any given time. - // - // Since the iScanEventMessage was null (i.e. its not been - // initialised) then its safe to store the client's message - // for completion later on when the scan engine has a real event. - - // Save the clients message for later until we receive an - // event callback from the scan engine. - iScanEventMessage = aMessage; - - // If we have at least one event ready to send to the client, then - // we deliver it to the client immediately. This could be possible - // if the client is slow to process an earlier event. - const TBool haveAtLeastOneEventPending = IsEventReady(); - if ( haveAtLeastOneEventPending ) - { - // We must deliver the oldest event to the client. - DeliverOldestEventToClientL(); // this will complete aMessage immediately. - } - } - else - { - // The client has already asked for scan events as we still - // have an existing (valid) iScanEventMessage object. - // - // This would imply a programming error in the client code - // so we punish the client by panicking it. - aMessage.Panic( KMemScanServerPanicCategory, EMemScanServerPanicRequestedScanEventsTwice ); - } - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::RequestScanEventsCancel() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::RequestScanEventsCancel(const RMessage2& aMessage) - { - // We only are able to cancel a client request if the client actually - // requested something. - // We can check whether a request is pending by using the IsNull method - // on our outstanding request object ("iScanEventMessage"). - if ( iScanEventMessage.IsNull() == EFalse ) - { - // The client has made a request, and we need to cancel it. - iScanEventMessage.Complete( KErrCancel ); - } - - - // If the client wants to cancel events, we should also empty - // the event buffer. - iEventBuffer.Reset(); - - aMessage.Complete( KErrNone ); - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::ScanInProgress() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::ScanInProgress(const RMessage2& aMessage) - { - TBool scanInProgress = iMseng->ScanInProgress(); - aMessage.Complete(static_cast (scanInProgress)); - } - - - -// From MMsengUIHandler: -// =========================================================================== - -// --------------------------------------------------------------------------- -// CMemScanServSession::StartL() -// --------------------------------------------------------------------------- -void CMemScanServSession::StartL() - { - SendEventToClientL( EMemScanEventScanningStarted ); - } - -// --------------------------------------------------------------------------- -// CMemScanServSession::QuitL() -// --------------------------------------------------------------------------- -void CMemScanServSession::QuitL(TInt aReason) - { - SendEventToClientL( EMemScanEventScanningFinished, aReason ); - } - -// --------------------------------------------------------------------------- -// CMemScanServSession::Error() -// --------------------------------------------------------------------------- -void CMemScanServSession::ErrorL(TInt aError) - { - SendEventToClientL( EMemScanEventScanningError, aError ); - } - -// =========================================================================== - - - - -// --------------------------------------------------------------------------- -// CMemScanServSession::SendEventToClientL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::SendEventToClientL( TMemScanEvent aEventType, - TInt aError ) - { - // We need to tell the client about the event that has taken place. - // The client event API expects to receive the event type, i.e. what - // kind of "thing" just happened, and also any associated error value - // (e.g. "Nothing went wrong" or, "we ran out of memory"). - - AddNewEventToBufferL( aEventType, aError ); - DeliverOldestEventToClientL(); - } - -// --------------------------------------------------------------------------- -// CMemScanServSession::AddNewEventToBufferL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::AddNewEventToBufferL( TMemScanEvent aEventType, - TInt aError ) - { - TMemScanEventPackage event; - event.iEvent = aEventType; - event.iError = aError; - - // Add the event to the event buffer. We will send this event to the - // client when the client is ready to accept it. - iEventBuffer.AppendL( event ); - } - -// --------------------------------------------------------------------------- -// CMemScanServSession::IsEventReady() -// -// --------------------------------------------------------------------------- -TBool CMemScanServSession::IsEventReady() const - { - // Returns whether we have at least one event in the buffer ready to send - // to the client. - const TInt count = iEventBuffer.Count(); - return ( count > 0 ); - } - - -// --------------------------------------------------------------------------- -// CMemScanServSession::DeliverOldestEventToClientL() -// -// --------------------------------------------------------------------------- -void CMemScanServSession::DeliverOldestEventToClientL() - { - // Fetch the oldest event from the buffer and deliver it - // to the client. - if ( iScanEventMessage.IsNull() == EFalse && IsEventReady() ) - { - // This next block of code converts the error number to look like - // a descriptor, since this is the only way of writing to the - // client's address space. - // - // We check that the client actually requested scan events before - // we try and write to its address space. If we don't do this - // then the kernel will panic our code with KERN-SVR 0 - // ("you're trying to use a null message object") - const TMemScanEventPackage& event = iEventBuffer[ 0 ]; - - TPckgC associatedErrorAsDescriptor( event.iError ); - iScanEventMessage.WriteL( 0, associatedErrorAsDescriptor ); - - // Now that we have written the error value, its safe to complete - // the clients asynchronous request which will end up calling - // the client's RunL method. - iScanEventMessage.Complete( event.iEvent ); - - // We've delivered the oldest event to the client, so now - // its safe to discard it. - iEventBuffer.Remove( 0 ); - } - } - - -// End of File