cbs/CbsServer/ServerSrc/CCbsServer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 11 Jun 2010 14:07:16 +0300
changeset 27 7eb70891911c
parent 0 ff3b6d0fd310
permissions -rw-r--r--
Revision: 201021 Kit: 2010123

/*
* Copyright (c) 2003-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:  This module contains the implementation of CCbsServer class 
*                member functions.
*   
*                This file contains the entry point for CbsServer.exe/dll.  
*
*/


// INCLUDE FILES

#include <e32svr.h>
#include <barsc.h>

#include "CbsCommon.h"
#include "CCbsScheduler.h"
#include "CbsServerConstants.h"
#include "CbsServerPanic.h"
#include "CCbsServer.h"
#include "CCbsSession.h"
#include "CbsUtils.h"

#include "CCbsRecEtel.h"
#include "CCbsDbImp.H"

#include "CCbsDbImp.H"
#include "CCbsRecEtel.h"

#include "CCbsDbImpSettings.H"
#include "CCbsDbImpTopicList.h"
#include "CCbsReceiverHelper.h"
#include "CCbsSatRefresh.h"

#include <e32property.h>
#include "CbsServerInternalPSKeys.h"
#include "CCbsShutdownMonitor.h"
#include "CbsLogger.h"
#include "CbsServerUid.h"


// LOCAL FUNCTION PROTOTYPES
LOCAL_C void InitServerL();

// ==================== LOCAL FUNCTIONS ====================

// -----------------------------------------------------------------------------
// InitServerL
// Initializes and starts CBS Server.
// Creates the active scheduler and an instance of the server.
// Returns: None
// -----------------------------------------------------------------------------
//
LOCAL_C void InitServerL()
    {
    CBSLOGSTRING("CBSSERVER: >>> InitServerL()");
    // perform init code under the cleanup stack
	User::RenameThread( KCbsServerName );
    
    // create server - if one of this name does not already exist
    TFindServer findCbsServer( KCbsServerName );
    TFullName pathName;

    RMutex serverStartMutex;
    TInt createErr( serverStartMutex.CreateGlobal( _L("CBSSERVERMTX") ) );
    if ( createErr )
        {
        TInt openErr( serverStartMutex.OpenGlobal( _L("CBSSERVERMTX") ) );
        User::LeaveIfError( openErr );
        }
    serverStartMutex.Wait();

    if ( findCbsServer.Next( pathName ) != KErrNone ) 
        {
        // start scheduler and server
        CCbsScheduler* scheduler = new (ELeave) CCbsScheduler;
        CleanupStack::PushL( scheduler );
        CActiveScheduler::Install( scheduler );

        CCbsServer* server = CCbsServer::NewL();
        CleanupStack::PushL( server );
        
        // The scheduler needs access to the server instance.
        scheduler->SetServer( server );
        
        // Set the key using Publish & Subscribe
        RProperty property;                       
        _LIT_SECURITY_POLICY_PASS( KCbsServerReadPolicy );
        _LIT_SECURITY_POLICY_S0( KCbsServerWritePolicy, KCbsServerUid3 );
                
        property.Define( KPSUidCellBroadcast, KCbsServerStarted, RProperty::EInt, KCbsServerReadPolicy, KCbsServerWritePolicy );
        CBSLOGSTRING("CBSSERVER: InitServerL(): Property defined.");
                
        property.Set( KPSUidCellBroadcast, KCbsServerStarted, 1 );
        CBSLOGSTRING("CBSSERVER: InitServerL(): Property set.");
                
        property.Close();

        serverStartMutex.Signal();
        serverStartMutex.Close();

        CBSLOGSTRING("CBSSERVER: InitServerL(): CbsServer created ok, starting active schduler.");

        RProcess::Rendezvous( KErrNone );
        
        // start fielding requests from clients
        CActiveScheduler::Start();
        CBSLOGSTRING("CBSSERVER: InitServerL(): CbsServer shutting down, destroying scheduler & server instances.");

        // finished when the scheduler stops
        CleanupStack::PopAndDestroy(2); // server, scheduler    
        }
    else
        {
        serverStartMutex.Signal();
        serverStartMutex.Close();
        }
    CBSLOGSTRING("CBSSERVER: <<< InitServerL()");
    }


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

// -----------------------------------------------------------------------------
// CCbsServer::CCbsServer
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CCbsServer::CCbsServer( 
    TInt aPriority )
    : CServer2( aPriority )
    {
    }

// -----------------------------------------------------------------------------
// CCbsServer::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCbsServer::ConstructL()
    {
    CBSLOGSTRING( "CBSSERVER: >>> CCbsServer::ConstructL()" );
    // Use PubSub to monitor shutdown event
    iShutdownMonitor = CCbsShutdownMonitor::NewL( *this );

    iReceiver = CCbsRecEtel::NewL();

    iDatabase = CCbsDbImp::NewL();

    iHelper = CCbsReceiverHelper::NewL( *iDatabase );

    iReceiver->SetInterface( iHelper );
    InitReceiverL();
    
    // Create the container index.
    iContainerIx = CObjectConIx::NewL();
    iContainer = NewContainerL();
    iIndex = CObjectIx::NewL();

	// Create SAT refresh listener
	TInt error( KErrNone );
	TRAP( error, iSatRefresh = CCbsSatRefresh::NewL( *this ));
    CBSLOGSTRING2( "CBSSERVER: CCbsServer::ConstructL(): CCbsSatRefresh::NewL error: %d", error );

    // Start the server
    if ( Start( KCbsServerName ) != KErrNone ) 
        {
        CbsServerPanic( ECbsServerStartFailed );
        }

    CBSLOGSTRING( "CBSSERVER: <<< CCbsServer::ConstructL()" );
    }

// -----------------------------------------------------------------------------
// CCbsServer::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CCbsServer* CCbsServer::NewL()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsServer::NewL()");
    CCbsServer* self = new ( ELeave ) CCbsServer( KCbsServerPriority );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    CBSLOGSTRING("CBSSERVER: <<< CCbsServer::NewL()");
    return self;
    }

    
// Destructor
CCbsServer::~CCbsServer()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsServer::~CCbsServer()");
    // Note: it is important to delete in correct order
    
    // The correct order is: 
    //        1st:    sessions, subsessions and other server related objects
    //        2nd:    receiver 
    //        3rd:    database

    if ( iIndex )
        {
        delete iIndex; 
        iIndex = NULL;        
        }
    
    if ( iContainer )
        {
        if ( iContainerIx )
            {
            iContainerIx->Remove( iContainer );
            iContainer = NULL;
            }        
        }

    // Delete subsessions
    if ( iContainerIx )
        {
        delete iContainerIx;
        iContainerIx = NULL;
        }    

    if ( iSatRefresh )
        {
        delete iSatRefresh;
        iSatRefresh = NULL;
        }
        
    if ( iReceiver )
        {
        delete iReceiver;
        iReceiver = NULL;
        }	
    
    if ( iDatabase )
        {
        delete iDatabase;
        iDatabase = NULL;
        }
        
    if ( iHelper )
        {
        delete iHelper;
        iHelper = NULL;
        }
           
    if ( iShutdownMonitor )
        {
        delete iShutdownMonitor;
        iShutdownMonitor = NULL;
        }
            
    CBSLOGSTRING("CBSSERVER: <<< CCbsServer::~CCbsServer()");
    }

// -----------------------------------------------------------------------------
// CCbsServer::NewSessionL
// Creates a new session (an instance of CCbsSession).
//   
// The method is meant to be called by the Symbian OS server framework and 
// so it should not be used in any other case.
//  
// The method leaves if the version given as parameter and the server
// version differ.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSession2* CCbsServer::NewSessionL( 
    const TVersion& aVersion,
    const RMessage2& /*aMessage*/ ) const
    {
    TVersion currentVersion( KCbsServerVersionMajor,
                             KCbsServerVersionMinor,
                             KCbsServerVersionBuild );

    // Check the client version
    if ( !User::QueryVersionSupported( currentVersion, aVersion ) )
        {
        User::Leave( KErrNotSupported );
        }

    // Create and return a new session
    return CCbsSession::NewL( *( CCbsServer* ) this );
    }

// -----------------------------------------------------------------------------
// CCbsServer::NewContainerL
// Creates a new session object container.
//  
// It is the responsibility of the caller to delete the object 
// container, when it is no longer used.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CObjectCon* CCbsServer::NewContainerL()
    {
    // Create the new container.
    return iContainerIx->CreateL();
    }

// -----------------------------------------------------------------------------
// CCbsServer::Database
// Returns a reference to the database.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
CCbsDbImp& CCbsServer::Database()
    {
    return *iDatabase;
    }

// -----------------------------------------------------------------------------
// CCbsServer::Receiver
// Returns a reference to the receiver.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CCbsRecEtel& CCbsServer::Receiver()
    {
    return *iReceiver;
    }

// -----------------------------------------------------------------------------
// CCbsServer::TotalTopicsDetected
// Returns the total number of detected (via topic detection feature)
// topics and then clears the counter.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//   
TInt CCbsServer::TotalTopicsDetected()
    {
    TInt count( iHelper->TopicsDetected() );
    iHelper->ClearTopicsDetectedCounter();
    return count;
    }

// -----------------------------------------------------------------------------
// CCbsServer::PanicClient
// Panics the client.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//  
void CCbsServer::PanicClient( 
    TInt aPanic ) const
    {
    __DEBUGGER();   // Debugger breakpoint in server's context.
    Message().Panic( KCbsServerName, aPanic );
    }

// -----------------------------------------------------------------------------
// CCbsServer::Shutdown
// Shuts down the server.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
void CCbsServer::Shutdown()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsServer::Shutdown()");
    Cancel();
    CActiveScheduler::Stop();
    CBSLOGSTRING("CBSSERVER: <<< CCbsServer::Shutdown()");
    }

// -----------------------------------------------------------------------------
// CCbsServer::ContainerIndex
// Returns the container index.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
CObjectConIx& CCbsServer::ContainerIndex()
    {
    return *iContainerIx;
    }

// -----------------------------------------------------------------------------
// CCbsServer::ServerMessage
// Returns the current IPC message.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
const RMessage2 CCbsServer::ServerMessage() const
    {
    return Message();
    }

// -----------------------------------------------------------------------------
// CCbsServer::ReturnObjectByHandle
// Returns a subsession object matching the given handle.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CCbsObject* CCbsServer::ReturnObjectByHandle( 
    TUint aHandle )
    {
    return ( CCbsObject* )iIndex->At( aHandle );
    }

// -----------------------------------------------------------------------------
// CCbsServer::DeleteObjectByHandle
// Deletes a subsession 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCbsServer::DeleteObjectByHandle( 
    TUint aHandle )
    {    
    // Find object and then delete it
    CCbsObject* object = ReturnObjectByHandle( aHandle );

    if ( object )
        {
        // Remove from index (and it will delete the object)
        iIndex->Remove( aHandle );
        }
    else
        {
        CbsServerPanic( EInvalidSessionObject );
        }
    }

// -----------------------------------------------------------------------------
// CCbsServer::Container
// Returns the object container
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CObjectCon& CCbsServer::Container()
    {
    return *iContainer;
    }

// -----------------------------------------------------------------------------
// CCbsServer::ObjectIx
// Returns the object index
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CObjectIx& CCbsServer::ObjectIx()
    {
    return *iIndex;
    }

// -----------------------------------------------------------------------------
// CCbsServer::InitReceiverL
// Initializes the receiver with values retrieved from the database.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
void CCbsServer::InitReceiverL()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsServer::InitReceiverL()");
    
    // DB leave trapped.
    TInt ignore( KErrNone );
    TRAP( ignore, iReceiver->LoadSimTopicsL() );
    CBSLOGSTRING2("CBSSERVER: CCbsServer::InitReceiverL(): LoadSimTopicsL() TRAPped error: %d", ignore);

    iReceiver->ApplyStateChangesL();
    
    CBSLOGSTRING("CBSSERVER: <<< CCbsServer::InitReceiverL()");    
    }
    
// -----------------------------------------------------------------------------
// CCbsServer::ReLoadSimTopicsL
// Initializes the receiver with values retrieved from the database.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
void CCbsServer::ReLoadSimTopicsL()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsServer::ReLoadSimTopicsL()");

    TInt ignore( KErrNone );
    
    TRAP( ignore, iReceiver->LoadSimTopicsL() );
    CBSLOGSTRING2("CBSSERVER: CCbsServer::ReLoadSimTopicsL(): LoadSimTopicsL() TRAPped error: %d", ignore);

    iReceiver->ApplyStateChangesL();
    
    CBSLOGSTRING("CBSSERVER: <<< CCbsServer::ReLoadSimTopicsL()");    
    }    

// ================= OTHER EXPORTED FUNCTIONS ==============

// -----------------------------------------------------------------------------
// E32Main
// E32Main implements the executable entry function.
// Creates a cleanup stack and runs the server. 
// Returns: Zero
// -----------------------------------------------------------------------------
//
GLDEF_C TInt E32Main()
    {
    __UHEAP_MARK;
    CTrapCleanup* cleanup = CTrapCleanup::New(); 

    TRAPD( error, InitServerL() ); 

    __ASSERT_ALWAYS( !error, User::Panic( KCbsServerName, error) );
    delete cleanup; 
    __UHEAP_MARKEND;
    return 0; 
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================
//  End of File