videoscheduler/SchedulerServer/src/CCseSchedulerUniPluginController.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:14:38 +0200
changeset 0 822a42b6c3f1
child 15 6c92a12abac0
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:    Base class for uni plugin controllers*
*/





// INCLUDE FILES
#include "CCseSchedulerUniPluginController.h"
#include "CseDebug.h"                           // Debug macros
#include "CCseSchedulerPluginStarter.h"
#include "CCseSchedulerLandLord.h"
#include <ipvideo/CCseScheduledProgram.h>
#include "CCseSchedulerTimer.h"
#include "CCseSchedulerServerEngine.h"

// EXTERNAL DATA STRUCTURES
// None.

// EXTERNAL FUNCTION PROTOTYPES  
// None.

// CONSTANTS
// None

// MACROS
// None.

// LOCAL CONSTANTS AND MACROS
// None.

// MODULE DATA STRUCTURES
// None.

// LOCAL FUNCTION PROTOTYPES
// None.


// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::CCseSchedulerUniPluginController
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CCseSchedulerUniPluginController::CCseSchedulerUniPluginController (
                                        CCseSchedulerServerEngine& aEngine,
                                        TInt32 aPluginUid ) :
                                        CCseSchedulerPluginControllerBase( aEngine, aPluginUid ),                                        
                                        iLandLord( NULL ),
                                        iIsLandLordWorking( EFalse )
    {
    CSELOGSTRING_HIGH_LEVEL(
        ">>>CCseSchedulerUniPluginController::CCseSchedulerUniPluginController");
        
    CSELOGSTRING_HIGH_LEVEL(
        "<<<CCseSchedulerUniPluginController::CCseSchedulerUniPluginController");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CCseSchedulerUniPluginController* CCseSchedulerUniPluginController::NewL(
                                        CCseSchedulerServerEngine& aEngine,
                                        TInt32 aPluginUid )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::NewL");
    
    CCseSchedulerUniPluginController* self =
            new( ELeave ) CCseSchedulerUniPluginController( aEngine, aPluginUid );
    CleanupStack::PushL( self );
    self->ConstructL( );
    CleanupStack::Pop( self );
    
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::NewL");
    return self;
    }

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::ConstructL()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::ConstructL");
    
    CCseSchedulerPluginControllerBase::ConstructL();
       
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::ConstructL");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::~CCseSchedulerUniPluginController
// Destructor.
// -----------------------------------------------------------------------------
//
CCseSchedulerUniPluginController::~CCseSchedulerUniPluginController()
    {
    CSELOGSTRING_HIGH_LEVEL(
        ">>>CCseSchedulerUniPluginController::~CCseSchedulerUniPluginController");
    delete iLandLord;
    iLandLord = NULL;
    CSELOGSTRING_HIGH_LEVEL(
        "<<<CCseSchedulerUniPluginController::~CCseSchedulerUniPluginController");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::RunPluginsL
// 
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::RunPluginsL()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::RunPluginsL");

    // Is there something to be run?!?
    if(iScheduleArray.Count() >0 )
        {
        // Check if there is security reasons for this schedule why this
        // schedule shouldn't be run
        if( iEngine.IsAllowedToRun( iScheduleArray[0]->DbIdentifier() ) )
            {
            // Check if LandLord is still working. If he is, we just fall through
            // because schedule will be kicked when current plugin completes
            if( iIsLandLordWorking == EFalse )
                {                    
                // When we come here in UniPluginController it means that there isn't any
                // threads running on LandLord side. Scrap the old if it exists and create new one.
                if ( iLandLord )
                    {
                    delete iLandLord;
                    iLandLord = NULL;
                    }
                
                iLandLord = CCseSchedulerLandLord::NewL( this );
                
                iLandLord->SetScheduleL( *iScheduleArray[0] );
                
                iEngine.IncreaseScheduleRunCountL( iScheduleArray[0]->DbIdentifier() );
                
                iIsLandLordWorking = ETrue;
                
                iLandLord->RunPluginL();
                }
            }
        else
            {
            // Schedule cannot be run anymore due to security reasons
            // Signal engine to remove schedule from DB
            iEngine.ScheduleNotValid( iScheduleArray[0]->DbIdentifier() );
            
            // Remove schedule own list
            delete iScheduleArray[0];
            iScheduleArray.Remove( 0 );
            
            // Call ourselves again.
            RunPluginsL();
            }            
        }
    else
        {
        // No schedules...!?!? REEEEESCHEDULE!!!
        iEngine.RequestReschedule();
        }

    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::RunPluginsL");
    }
    
// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::SetSchedulesL
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::SetSchedulesL(
                                            RPointerArray<CCseScheduledProgram>& aScheduleArray )
    {
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::SetSchedules");

    //  The aScheduleArray parameter contains schedules which are either before
    //  or at the same time as the existing ones in the iScheduleArray.
    //  Just destroy the old ones and replace with new ones.
    //  Also cancel the timer because the schedule to run may be different

    iScheduleArray.ResetAndDestroy();
    iTimer->Cancel();

	// Go through all given schedules and copy them our array
	for( TInt i = 0; i < aScheduleArray.Count(); i++)
	    {
        CCseScheduledProgram* schedule =
                CCseScheduledProgram::NewL(*aScheduleArray[i] );
        CleanupStack::PushL( schedule );

	    iScheduleArray.AppendL( schedule );

	    CleanupStack::Pop( schedule );
	    }

    //  If we have schedules, set the timer
    if (iScheduleArray.Count() > 0  && !iIsLandLordWorking)
        {
        //  All the schedules have same time
        iTimer->SetTimer( iScheduleArray[0]->StartTime() );
        }

	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::SetSchedules");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::ScheduledEventCompleted
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::ScheduleCompletedL( const TUint32 aDbIdentifier,
                                                           TInt aCompletitionCode )
	{	
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::ScheduleCompletedL");
    
    if ( aCompletitionCode == KErrNone )
        {
        ScheduleCompletedSuccesfullyL( aDbIdentifier );
        }
    else
        {        
        HandleScheduleErrorL( aDbIdentifier, aCompletitionCode );
        }    
     
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::ScheduleCompletedL");
	}
	
// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::ScheduleCompletedSuccesfullyL
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::ScheduleCompletedSuccesfullyL( const TUint32 aDbIdentifier )
	{
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::ScheduleCompletedSuccesfullyL");
	
	// Remove completed schedule from list
    for ( TInt i = iScheduleArray.Count(); i > 0; i--)
        {
        if( iScheduleArray[i-1]->DbIdentifier() == aDbIdentifier )
            {
            delete iScheduleArray[i-1];
            iScheduleArray.Remove( i-1 );                
            }
        }

    // After all this LandLord has finished everything. He may rest now    
    iIsLandLordWorking = EFalse;            
        
    // Notify engine about completition.
    iEngine.ScheduleCompletedSuccesfullyL( aDbIdentifier );
    
    // If there is still schedule(s), set timer for it
    if( iScheduleArray.Count() > 0 )
        {
        iTimer->SetTimer( iScheduleArray[0]->StartTime() );
        }    
    
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::ScheduleCompletedSuccesfullyL");	
	}
	
// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::HandleScheduleErrorL
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::HandleScheduleErrorL( const TUint32 aDbIdentifier,
                                                            TUint32 aCompletitionCode )
	{	
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::HandleScheduleErrorL");
	
    // Remove completed schedule from list
    for ( TInt i = iScheduleArray.Count(); i > 0; i--)
        {
        if( iScheduleArray[i-1]->DbIdentifier() == aDbIdentifier )
            {
            delete iScheduleArray[i-1];
            iScheduleArray.Remove( i-1 );                
            }
        }

    // After all this LandLord has finished everything. He may rest now    
    iIsLandLordWorking = EFalse;            
	
	// Here we could try to handle plugin errors. Problem is that scheduler doesn't
	// know anything about schedule it is running and so there cannot be tailored
	// error handling for each plugin. In the end, we just complete schedule
	// to engine with error code (ends up removing schedule from DB).
	iEngine.ScheduleCompletedWithErrorL( aDbIdentifier, aCompletitionCode );
	
	// If there is still schedule(s), set timer for it
    if( iScheduleArray.Count() > 0 )
        {
        iTimer->SetTimer( iScheduleArray[0]->StartTime() );
        }

	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::HandleScheduleErrorL");
	}
	
// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::TimerErrorL
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::TimerErrorL( const TInt32 aError )
	{	
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::TimerErrorL");
	
	if ( aError == KErrAbort )
		{
		 // System time changed. Make sanity check and start timer again.
		CSELOGSTRING_HIGH_LEVEL(
		    ">>>CCseSchedulerUniPluginController::TimerErrorL, system time has changed");
		if ( iScheduleArray.Count() > 0 )
			{
			TTime now;
			now.UniversalTime();
			// Time still in the future
			if ( now < iScheduleArray[0]->StartTime() )
				{
				iTimer->SetTimer( iScheduleArray[0]->StartTime() );
				}
			else
				{
				// If schedule is in the past let the "normal" route decide when
				// it is he's her time to be run
				RunPluginsL();
				}
			}
		return; 
		}

	if ( aError == KErrUnderflow )
		{
		 // Scheduled time is in the past, pass it to notifier. It should decide what to do
		CSELOGSTRING_HIGH_LEVEL(
		    ">>>CCseSchedulerServerEngine::TimerErrorL, scheduled time is in the past");
		RunPluginsL();
		return;
		}
			
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::TimerErrorL");
	}

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::ClearController
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerUniPluginController::ClearControllerL( )
	{	
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::ClearControllerL");	

    iLandLord->ClearL();
        
    iScheduleArray.ResetAndDestroy();
        
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::ClearControllerL");
	}

// -----------------------------------------------------------------------------
// CCseSchedulerUniPluginController::ClearController
//
// -----------------------------------------------------------------------------
//
TBool CCseSchedulerUniPluginController::IsControllerActive( )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerUniPluginController::IsControllerActive");
    
    CSELOGSTRING2_HIGH_LEVEL("<<<CCseSchedulerUniPluginController::IsControllerActive: %d",
                            iIsLandLordWorking);
    
    return iIsLandLordWorking;
    }

// End of file.