contentpublishingsrv/contentpublishingserver/cpserver/src/cpactionhandlerthread.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contentpublishingsrv/contentpublishingserver/cpserver/src/cpactionhandlerthread.cpp Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,410 @@
+/*
+* Copyright (c) 2008 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:
+*
+*/
+
+#include "cpactionhandlerthread.h"
+#include "cpserverdef.h"
+#include "cpserveractionmanager.h"
+#include "cpglobals.h"
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TInt CPExecutionThreadFunction( TAny* aParam )
+ {
+ ASSERT( aParam );
+ CCPActionHandlerThread* actionHandlerThread =
+ reinterpret_cast<CCPActionHandlerThread*>( aParam );
+ return actionHandlerThread->ThreadFunction();
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread* CCPActionHandlerThread::NewL()
+ {
+ CCPActionHandlerThread* self = NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread* CCPActionHandlerThread::NewLC()
+ {
+ CCPActionHandlerThread* self = new ( ELeave ) CCPActionHandlerThread;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread::~CCPActionHandlerThread()
+ {
+ if ( ExecutionThreadRunning() && iActionExecutorAO )
+ {
+ // stop action execution thread
+
+ // request notification when action execution thread terminates
+ TRequestStatus exitStatus;
+ iActionExecThread.Logon( exitStatus );
+
+ // passing NULL as action parameters will cause the action executor to
+ // stop active scheduler in command execution thread
+ iActionExecutorAO->SetActionParams( NULL );
+ // ask action executor to execute the action
+ TRequestStatus* actionExecutorAOStatus =
+ iActionExecutorAO->RequestStatus();
+ iActionExecThread.RequestComplete( actionExecutorAOStatus, KErrNone );
+
+ // wait for the action execution thread to terminate
+ User::WaitForRequest( exitStatus );
+ }
+ iActionExecThread.Close();
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::ExecuteL(
+ const CLiwGenericParamList& aActionParams )
+ {
+ StartExecutionThreadIfNeededL();
+
+ ASSERT( iActionExecutorAO );
+ iActionExecutorAO->SetActionParams( &aActionParams );
+
+ // create rendezvous so that we are notified when action
+ // execution finishes
+ TRequestStatus actionExecutionStatus = KRequestPending;
+ iActionExecThread.Rendezvous( actionExecutionStatus );
+
+ // request action execution by completing request for the AO running
+ // in the action execution thread
+ TRequestStatus* actionExecutorAOStatus =
+ iActionExecutorAO->RequestStatus();
+ iActionExecThread.RequestComplete( actionExecutorAOStatus, KErrNone );
+
+ // wait until action execution finishes
+ User::WaitForRequest( actionExecutionStatus );
+
+ TInt err = actionExecutionStatus.Int();
+ // please note that checking actionExecutionStatus is not a reliable way of
+ // determining whether everything is OK because if plugin panics with
+ // reason (panic number) KErrNone, actionExecutionStatus will contain KErrNone
+ if ( !ExecutionThreadRunning() )
+ {
+ // action execution thread died,
+ // iActionExecutorAO pointer is no longer valid
+ iActionExecutorAO = NULL;
+ if ( err >= 0 )
+ {
+ err = KErrDied;
+ }
+ }
+ else
+ {
+ iActionExecutorAO->SetActionParams( NULL );
+ }
+
+ User::LeaveIfError( err );
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+ void CCPActionHandlerThread::StartExecutionThreadIfNeededL()
+ {
+ if ( !ExecutionThreadRunning() )
+ {
+ TBuf<KThreadNameLimit> threadName;
+ if ( iActionExecThreadStarted )
+ {
+ iActionExecThread.Close();
+ }
+
+ // create action execution thread
+ threadName.Format( KCPServerPluginThreadName, ++iThreadNum );
+ TInt err = iActionExecThread.Create( threadName,
+ CPExecutionThreadFunction,
+ KDefaultStackSize,
+ KCPServerPluginThreadMinHeapSize,
+ KCPServerPluginThreadMaxHeapSize,
+ reinterpret_cast<TAny*>( this ) );
+ User::LeaveIfError( err );
+
+ // create rendezvous so that we are notified when the thread
+ // has started
+ TRequestStatus threadStatus;
+ iActionExecThread.Rendezvous( threadStatus );
+
+ // start the action execution thread
+ iActionExecThread.Resume();
+
+ // wait for the thread to start
+ User::WaitForRequest( threadStatus );
+
+ User::LeaveIfError( threadStatus.Int() );
+
+ iActionExecThreadStarted = ETrue;
+ ASSERT( ExecutionThreadRunning() );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// RThread::ExitType() returns EExitPending if the thread is alive or has not
+// been started yet. There is a member variable, iActionExecThreadStarted
+// which tells if the thread was started or not. Combining the information
+// from the member variable and RThread::ExitType() allows us to determine if
+// the thread is running (alive).
+// ---------------------------------------------------------------------------
+//
+ TBool CCPActionHandlerThread::ExecutionThreadRunning()
+ {
+ TBool actionExecThreadDidNotDie =
+ iActionExecThread.ExitType() == EExitPending;
+
+ TBool threadRunning =
+ iActionExecThreadStarted && actionExecThreadDidNotDie;
+
+ // if the thread is alive, it must have created an active object for
+ // executing actions in plugins; verify that it is the case
+ ASSERT( !threadRunning || ( threadRunning && iActionExecutorAO ));
+
+ return threadRunning;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+ CCPActionHandlerThread::CCPActionHandlerThread()
+ {
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::ConstructL()
+ {
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TInt CCPActionHandlerThread::ThreadFunction()
+ {
+ __UHEAP_MARK;
+
+ CServerEikonEnv* env = new CServerEikonEnv;
+ if ( !env )
+ {
+ return KErrNoMemory;
+ }
+ CServerAppUi* ui = new CServerAppUi;
+ if ( !ui )
+ {
+ delete env;
+ return KErrNoMemory;
+ }
+
+ TRAPD( err,
+ env->ConstructL();
+ env->DisableExitChecks( ETrue );
+ ui->ConstructL();
+
+ iActionExecutorAO = CActionExecutorAO::NewL();
+
+ // notify the main thread that action execution thread
+ // has successfully started
+ RThread::Rendezvous( KErrNone );
+
+ CActiveScheduler::Start();
+ );
+
+ delete iActionExecutorAO;
+ iActionExecutorAO = NULL;
+
+ ui->PrepareToExit();
+ env->DestroyEnvironment();
+
+ __UHEAP_MARKEND;
+
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CContentHarvesterEikonEnv::DestroyEnvironment
+//
+// -----------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CServerEikonEnv::DestroyEnvironment()
+ {
+ CEikonEnv::DestroyEnvironment( );
+ }
+
+// -----------------------------------------------------------------------------
+// CContentHarvesterEikonEnv::ConstructL
+//
+// -----------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CServerEikonEnv::ConstructL()
+ {
+ CEikonEnv::ConstructL( EFalse );
+ SetAutoForwarding( ETrue );
+ User::SetPriorityControl( EFalse );
+ }
+// -----------------------------------------------------------------------------
+// CContentHarvesterAppUi::~CContentHarvesterAppUi
+//
+// -----------------------------------------------------------------------------
+//
+CCPActionHandlerThread::CServerAppUi::~CServerAppUi()
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CContentHarvesterAppUi::ConstructL
+//
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CServerAppUi::ConstructL()
+ {
+ CEikAppUi::BaseConstructL( ENoAppResourceFile | ENoScreenFurniture );
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread::CActionExecutorAO*
+CCPActionHandlerThread::CActionExecutorAO::NewL()
+ {
+ CActionExecutorAO* self = NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread::CActionExecutorAO*
+CCPActionHandlerThread::CActionExecutorAO::NewLC()
+ {
+ CActionExecutorAO* self = new ( ELeave ) CActionExecutorAO();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread::CActionExecutorAO::~CActionExecutorAO()
+ {
+ delete iActionManager;
+ }
+
+// ---------------------------------------------------------------------------
+// Any code executed in this method must not leave!
+// This way we avoid implementing RunError while making sure that
+// Rendezvous will always be called
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CActionExecutorAO::RunL()
+ {
+ if( iActionParams )
+ {
+ // execute action
+ TRAPD( err, iActionManager->ExecuteL( *iActionParams ) );
+
+ // notify the main thread that action execution has finished
+ RThread::Rendezvous( err );
+
+ // wait until another action execution is requested
+ iStatus = KRequestPending;
+ SetActive();
+ }
+ else
+ {
+ CActiveScheduler::Stop();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CActionExecutorAO::DoCancel()
+ {
+ TRequestStatus* myRequestStatus = &iStatus;
+ User::RequestComplete( myRequestStatus, KErrCancel );
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TRequestStatus* CCPActionHandlerThread::CActionExecutorAO::RequestStatus()
+ {
+ return &iStatus;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CActionExecutorAO::SetActionParams(
+ const CLiwGenericParamList* aActionParams )
+ {
+ iActionParams = aActionParams;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CCPActionHandlerThread::CActionExecutorAO::CActionExecutorAO()
+ : CActive( CActive::EPriorityLow )
+ {
+ CActiveScheduler::Add( this );
+
+ // wait until action execution is requested
+ iStatus = KRequestPending;
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CCPActionHandlerThread::CActionExecutorAO::ConstructL()
+ {
+ iActionManager = CCPActionManager::NewL();
+ }