ncdengine/engine/src/catalogsclientserverserver.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/engine/src/catalogsclientserverserver.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,526 @@
+/*
+* 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 "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 CCatalogsClientServerServer
+*
+*/
+
+
+#include "catalogsclientserverserver.h"
+#include "catalogsclientserverserversession.h"
+#include "catalogsserverdefines.h"
+#include "catalogsserverengine.h"
+#include "catalogscontext.h"
+
+#include "catalogsdebug.h"
+
+CCatalogsClientServerServer* CCatalogsClientServerServer::iCatalogsServer = NULL;
+
+// Replaced with USE_BUILD_SCRIPT when using build script
+#define DUMMY_DEFINE
+
+#ifdef CATALOGS_UNDERTAKER
+#ifdef USE_BUILD_SCRIPT
+_LIT( KCatalogsUndertakerFilename, "ncdundertaker_APP_NAME_POSTFIX" );
+#else
+_LIT( KCatalogsUndertakerFilename, "ncdundertaker_20019119" );
+#endif // USE_BUILD_SCRIPT
+#endif
+
+// Capability set required from clients. Consists of CAP_APPLICATION capability set.
+static _LIT_SECURITY_POLICY_C7(
+    KCatalogsServerConnectPolicy1,
+    ECapabilityNetworkServices,
+    ECapabilityLocalServices,
+    ECapabilityLocation,
+    ECapabilityReadUserData,
+    ECapabilityWriteUserData,
+    ECapabilityReadDeviceData,
+    ECapabilityWriteDeviceData );
+    
+static _LIT_SECURITY_POLICY_C2(
+    KCatalogsServerConnectPolicy2,
+    ECapabilitySwEvent,
+    ECapabilityUserEnvironment );
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+CCatalogsClientServerServer* CCatalogsClientServerServer::NewLC()
+    {
+    CCatalogsClientServerServer* self = new( ELeave )
+        CCatalogsClientServerServer( CActive::EPriorityLow - 20 );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+CCatalogsClientServerServer::CCatalogsClientServerServer( TInt aPriority ) :
+    CServer2( aPriority )
+    {
+    iCatalogsServer = this;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+CCatalogsClientServerServer::~CCatalogsClientServerServer()
+    {
+    DLTRACEIN((""));
+    // Usually at this point all sessions are already destroyed.
+    // If not, we have to go through all sessions and destroy
+    // all references to the objects to which references might be lost
+    // if the engine was destroyed first.
+    // Also when doing it this way when the engine is destroyed,
+    // provider can do the final killing of those objects
+    iSessionIter.SetToFirst();
+    CSession2* baseSession = NULL;
+    CCatalogsClientServerServerSession* session = NULL;
+    baseSession = iSessionIter++;
+    while ( baseSession != NULL )
+        {
+        DLTRACE(("Calling ClientSideSessionDown"));
+        // When going down, act as the client side would have died
+        // ->call ClientSideSessionDown for each session
+        session = 
+            static_cast<CCatalogsClientServerServerSession*>( baseSession );
+        session->ClientSideSessionDown();
+        baseSession = iSessionIter++;
+        DLTRACE(("ClientSideSessionDown called"));
+        }
+    
+    DLTRACE(("Delete engine"));
+    // This is destroyed before destroying container, so possible
+    // resources are freed in its destructor and from the container 
+    // in here.
+    // Other way would end up destroying already destroyed stuff.
+    delete iEngine;
+
+    DLTRACE(("Engine deleted"));
+    iShutdownOperations.ResetAndDestroy();
+    
+    // If container is going to be removed, it has to be done before
+    // it is destroyed by destroying the container index.
+    if ( iContainer != NULL )
+        {
+        DLTRACE(("Remove container"));
+        RemoveContainer( iContainer );        
+        DLTRACE(("Container removed"));
+        }
+    iContainer = NULL;
+    
+    DLTRACE(("Deleting container index"));
+    delete iContainerIndex;
+
+#ifdef CATALOGS_UNDERTAKER
+
+    iUndertakerProcess.Close();
+
+#endif 
+
+    DLTRACEOUT((""));
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::ConstructL()
+    {
+    DLTRACEIN((""));
+    User::LeaveIfError( User::RenameThread( KCatalogsServerName ) );
+#ifdef CATALOGS_UNDERTAKER
+
+    DLINFO(( "Creating undertaker process" ));
+    TInt err = iUndertakerProcess.Create( KCatalogsUndertakerFilename, KNullDesC() );
+    if( err != KErrNone )
+        {
+        DLERROR(( "Creating undertaker process failed with %d", err ));
+        }
+    iUndertakerProcess.SetPriority( (TProcessPriority)450 );  // EPriorityHigh
+    
+    RThread thisThread;
+    DLINFO(( _L("Setting undertaker parameter 15 as %S"), &thisThread.FullName() ));
+    
+    err = iUndertakerProcess.SetParameter( 15, thisThread.FullName() );
+    if( err != KErrNone )
+        {
+        DLERROR(( "Parameter setting failed with %d", err ));
+        }
+    thisThread.Close();
+    iUndertakerProcess.Resume();
+
+#endif
+
+    iContainerIndex = CObjectConIx::NewL();
+    iContainer = NewContainerL();
+
+	iEngine = CCatalogsServerEngine::NewL();
+    // Add the server to the active scheduler
+    StartL( KCatalogsServerName );
+    DLTRACEOUT((""));
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::IncrementSessions()
+    {
+    iSessionCount++;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::DecrementSessions()
+    {
+    iSessionCount--;
+
+    // No more clients, shutdown
+    if ( iSessionCount <= 0 )
+        {
+        CActiveScheduler::Stop();
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::HandleSessionRemoval( 
+    MCatalogsSession& aSession )
+    {
+    DASSERT( iEngine );
+    
+    // We don't want to go further unless the context has been created
+    if ( aSession.ContextPtr() )
+        {
+        iEngine->HandleSessionRemoval( aSession );
+        // Execute shutdown operations
+        OperateShutdownOperations( aSession.Context(), ETrue );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+CObjectCon* CCatalogsClientServerServer::NewContainerL()
+	{
+    // Return a new object container
+	return iContainerIndex->CreateL();
+	}
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::RemoveContainer( CObjectCon* aCon )
+	{
+	DASSERT( iContainerIndex );
+	iContainerIndex->Remove( aCon );
+	}
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::CreateProviderL( 
+    MCatalogsSession& aSession, 
+    TInt aProviderIdentifier,
+    TInt& aHandle,
+    TUint32 aProviderOptions )
+    {
+    DLTRACEIN((""));
+    
+    iEngine->CreateProviderL( aSession,
+                              aProviderIdentifier, 
+                              aHandle,
+                              aProviderOptions );
+
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+TInt CCatalogsClientServerServer::NewInstanceId()
+    {
+    DLTRACEIN((""));
+    return iSessionInstanceIdCounter++;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::AddObjectToContainerL( CObject* aObject )
+    {    
+    // If possible, change trap-implementation to something else.
+    // This is just a simple way to do this.
+    TRAPD( err, iContainer->AddL( aObject ) );
+    DLTRACE(("err: %d", err ));
+    if ( err == KErrAlreadyExists || err == KErrNone )
+        {        
+        return;
+        }
+    else
+        {
+        User::Leave( err );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::ThreadFunctionL()
+    {
+    DLTRACEIN((""));
+    DCHECK_HEAP
+    // Construct an active scheduler for the server
+
+    DLINFO(( "Creating active schduler" ));
+    CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
+    CleanupStack::PushL( activeScheduler );
+
+    // Install active scheduler
+    // No need to check whether an active scheduler is already installed
+    // as this is a new thread, so there won't be one
+    DLINFO(( "Installing active schduler" ));
+    CActiveScheduler::Install( activeScheduler );
+
+    // Construct our server
+    CCatalogsClientServerServer::NewLC(); // anonymous
+
+    DLINFO(( "Opening semaphore" ));
+    RSemaphore semaphore;
+    User::LeaveIfError(
+        semaphore.OpenGlobal( KCatalogsServerSemaphoreName ));
+    
+    DLINFO(( "Signalling and closing semaphore" ));
+    // Semaphore opened ok
+    semaphore.Signal();
+    semaphore.Close();
+
+    // Start handling requests, operation will stop here until
+    // the server dies
+    CActiveScheduler::Start();
+
+    DLINFO(("Server has shut down"));
+
+    // The server has been shut down, clean up
+    CleanupStack::PopAndDestroy( 2, activeScheduler );
+    DLTRACEOUT((""));
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+TInt CCatalogsClientServerServer::ThreadFunction( TAny* /*aNone*/ )
+    {
+#ifdef CATALOGS_BUILD_CONFIG_HEAP_MARKS    
+    __UHEAP_MARK;
+#endif    
+    DLINIT;
+    
+    DLTRACEIN((""));
+    
+    CTrapCleanup* cleanupStack = CTrapCleanup::New();
+    TRAPD( err, ThreadFunctionL() );
+    
+    DLTRACE(( "err: %d", err ));
+    delete cleanupStack;
+    cleanupStack = NULL;
+    
+    DLTRACEOUT((""));
+
+    DLUNINIT;
+#ifdef CATALOGS_BUILD_CONFIG_HEAP_MARKS    
+    __UHEAP_MARKEND; 
+#endif    
+    return err;    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+TInt CCatalogsClientServerServer::RunError( TInt aError )
+    {
+    DLTRACEIN(( "aError=%d", aError ));    
+
+    // Complete the message being processed, although the state of
+    // the server is undetermined
+    DLERROR(( "Completing last message with %d", aError ));
+    Message().Complete( aError );
+
+    DLTRACEOUT(("KErrNone"));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+CSession2* CCatalogsClientServerServer::NewSessionL( 
+    const TVersion& aVersion,
+    const RMessage2& aMsg ) const
+    {
+    DLTRACEIN((""));
+        
+    // Check whether the server is compatible with the 
+    // requested version
+    if ( !User::QueryVersionSupported(
+           TVersion(
+               KCatalogsServerMajorVersionNumber,
+               KCatalogsServerMinorVersionNumber,
+               KCatalogsServerBuildVersionNumber
+               ),
+           aVersion))
+        {        
+        User::Leave( KErrNotSupported );
+        }
+
+    DLINFO(("Checking client capabilities"));
+    // Check the client for required capabilities
+    if (!KCatalogsServerConnectPolicy1().CheckPolicy(
+        aMsg, __PLATSEC_DIAGNOSTIC_STRING("CCatalogsClientServerServer::NewSessionL, KCatalogsServerConnectPolicy1") ) ||
+        !KCatalogsServerConnectPolicy2().CheckPolicy(
+        aMsg, __PLATSEC_DIAGNOSTIC_STRING("CCatalogsClientServerServer::NewSessionL, KCatalogsServerConnectPolicy2" ) ) )
+        {
+        DLINFO(("Client capability check failed"));
+        User::Leave( KErrPermissionDenied );
+        }
+
+    // Context is not created here for the session, because
+    // user given uid cannot be received by this function from
+    // the client-side and it is nicer to create the whole
+    // context-object in one place.
+
+    DLTRACEOUT((""));
+        
+    // Create a new session
+    RThread client;
+    return CCatalogsClientServerServerSession::NewL(
+        client,
+        *const_cast<CCatalogsClientServerServer*>( this ) );
+    }
+
+
+/**
+ * Platform dependant entry points
+ */
+
+IMPORT_C TInt WinsMain();
+EXPORT_C TInt WinsMain()
+	{
+	// WINS DLL entry-point. Just return the real thread function 
+    // cast to TInt
+	return reinterpret_cast<TInt>( 
+	    &CCatalogsClientServerServer::ThreadFunction );
+	}
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+GLDEF_C TInt E32Main()
+    {
+    return CCatalogsClientServerServer::ThreadFunction( NULL );
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+TInt CCatalogsClientServerServer::AddShutdownOperation( 
+    CCatalogsShutdownOperation* aOperation )
+    {
+    DLTRACEIN((""))
+    DASSERT( aOperation );
+    TInt err = iCatalogsServer->iShutdownOperations.Append( aOperation );
+
+    if ( err == KErrNone )
+        {
+        aOperation->SetObserver( *iCatalogsServer );
+        iCatalogsServer->IncrementSessions();
+        }
+    else
+        {
+        DLERROR(("Appending failed: %d", err));
+        delete aOperation;
+        }
+    
+    return err;    
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::ShutdownOperationComplete( 
+    CCatalogsShutdownOperation* aOperation, 
+    TInt aError )
+    {
+    DLTRACEIN(("aError: %d", aError));
+    (void) aError;
+    iShutdownOperations.Remove( iShutdownOperations.Find( aOperation ) );
+    delete aOperation;
+    DecrementSessions();
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+// 
+void CCatalogsClientServerServer::OperateShutdownOperations( 
+    const MCatalogsContext& aContext,
+    TBool aExecute )
+    {
+    DLTRACEIN((""));
+    TInt count = iShutdownOperations.Count();
+    const TUid uid( aContext.FamilyId() );
+    // Iterating backwards because an executed operation may be removed
+    // from the queue while we are iterating through it
+    while( count-- )
+        {
+        if ( iShutdownOperations[ count ]->FamilyUid() == uid ) 
+            {
+            if ( aExecute )
+                {
+                iShutdownOperations[ count ]->Execute();
+                }
+            else
+                {
+                iShutdownOperations[ count ]->Cancel();
+                }
+            }
+        }
+    }