ncdengine/engine/src/catalogsengine.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/engine/src/catalogsengine.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,318 @@
+/*
+* 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:   Describes a factory to return a handle to the Catalogs engine
+*
+*/
+
+
+#include <e32base.h>
+#include <e32property.h>
+#include <ecom/ecom.h>
+
+#include "catalogsengine.h"
+#include "catalogsdebug.h"
+#include "catalogserrors.h"
+#include "catalogsconstants.h"
+ 
+#ifndef CATALOGS_ECOM
+
+static void CleanupMutex( TAny* aMutexPtr )
+    {
+    DLTRACEIN((""));
+    RMutex* mutex = static_cast< RMutex* >( aMutexPtr );
+    DLINFO(( "Signalling and closing engine mutex" ));
+    mutex->Signal();
+    mutex->Close();
+    }
+
+
+static void GetMutexLC( RMutex& aMutex )
+    {
+    DLTRACEIN((""));
+
+    // First try to open the global mutex.
+    DLINFO(( "Trying to open engine mutex" ));
+
+    TInt mutexOpenErr = aMutex.OpenGlobal( KCatalogsEngineMutex );
+    if( mutexOpenErr == KErrNotFound )
+        {
+        DLINFO(( "Mutex was not found, trying to create." ));
+        mutexOpenErr = aMutex.CreateGlobal( KCatalogsEngineMutex );
+        if( mutexOpenErr == KErrAlreadyExists )
+            {
+            // Someone beat us to it. Try opening again.
+            DLINFO(( "Mutex was just created. Trying to open." ));
+            mutexOpenErr = aMutex.OpenGlobal( KCatalogsEngineMutex );
+            }
+        }
+
+    if( mutexOpenErr != KErrNone )
+        {
+        DLERROR(( "Mutex open failed with %d", mutexOpenErr ));
+        DLTRACEOUT(( "LEAVE %d", mutexOpenErr ));
+        User::Leave( mutexOpenErr );
+        }
+
+    DLINFO(( "Waiting for engine mutex..." ));
+    aMutex.Wait();
+    DLINFO(( "Got property mutex" ));
+
+    // Push a cleanup item for signalling and closing the mutex.
+    CleanupStack::PushL( TCleanupItem( CleanupMutex, &aMutex ) );
+
+    DLTRACEOUT((""));
+    }
+
+static TBool IsMaintenanceLockOnL()
+    {
+    DLTRACEIN((""));
+
+    // Get Catalogs Engine maintenance P&S variable
+    DLINFO(( "Reading maintenance lock value" ));
+    
+    TInt value;
+    TInt err = RProperty::Get( 
+        KCatalogsEnginePropertyCategory, 
+        KCatalogsEnginePropertyKeyMaintenanceLock,
+        value );
+
+    if( err == KErrNone )
+        {
+        DLINFO(( "Maintenance lock value %08x", value ));
+
+        DLTRACEOUT(( "%d", value != 0 ));
+        return value != 0;
+        }
+
+    else if( err != KErrNotFound )
+        {
+        DLERROR(( "Maintenance lock read failed with %d", err ));
+        DLTRACEOUT(( "LEAVE %d", err )); 
+        User::Leave( err );
+        }
+
+    // Maintenance P&S variable not set, not in maintenance mode.
+    DLTRACEOUT(( "EFalse" ));
+    return EFalse;
+    }
+
+
+static void SetMaintenanceLockL( TBool aLock )
+    {
+    DLTRACEIN(( "Writing %d to maintenance lock P&S", aLock ));
+    
+    // Write maintenance lock property.
+    DLINFO(( "Writing maintenance lock property" ));
+    TInt err = RProperty::Set(
+        KCatalogsEnginePropertyCategory,
+        KCatalogsEnginePropertyKeyMaintenanceLock,
+        aLock );
+
+    if( err == KErrNotFound )
+        {
+        DLINFO(( "Maintenance lock property not found, invoking server to define it" ));
+        
+        // P&S variable is defined in the server process. Connect to server to
+        // accomplish this.
+        MCatalogsEngineObserver* nullObserver = NULL;
+        CCatalogsEngine* engine = CCatalogsEngine::NewLC( *nullObserver );
+
+        err = engine->Connect( TUid::Uid( 0 ) );
+
+        // Engine no longer needed, close, release and delete.
+        DLINFO(( "Connect returned %d. Closing engine object.", err ));
+        engine->Close();
+
+        DLINFO(( "Deleting engine object" ));
+        CleanupStack::PopAndDestroy( engine );
+
+        if( err == KErrNone )
+            {
+            // The maintenance lock property should be defined now, try again.
+            DLINFO(( "Writing maintenance lock property" ));
+            err = RProperty::Set(
+                KCatalogsEnginePropertyCategory,
+                KCatalogsEnginePropertyKeyMaintenanceLock,
+                aLock );
+            }
+        }
+
+    if( err != KErrNone )
+        {
+        DLERROR(( "Maintenance lock set failed, error %d", err ));
+        DLTRACEOUT(( "LEAVE %d", err ));
+        User::Leave( err );
+        }
+
+    DLTRACEOUT((""));
+    }
+
+
+EXPORT_C CCatalogsEngine::TState CCatalogsEngine::StateL()
+    {
+    DLTRACEIN((""));
+
+    RMutex mutex;
+    GetMutexLC( mutex );
+
+    TState result = EStateNormal;
+
+    if( IsMaintenanceLockOnL() )
+        {
+        // Either EStatePrepareMaintenance or EStateMaintenance.
+        DLINFO(( "Maintenance lock is on." ));
+
+        // Check if engine instances exist. This can be determined by mutex usage:
+        // all existing instances hold a handle to the mutex. If there are handles
+        // in addition to the one held here, other instances exist.
+        THandleInfo mutexHandleInfo;
+        mutex.HandleInfo( &mutexHandleInfo );
+        
+        DLINFO(( "Mutex handle in-process count %d, process count %d",
+            mutexHandleInfo.iNumOpenInProcess, mutexHandleInfo.iNumProcesses ));
+        
+        if( mutexHandleInfo.iNumOpenInProcess > 1 || 
+            mutexHandleInfo.iNumProcesses > 1 )
+            {
+            result = EStatePrepareMaintenance;
+            }
+        else
+            {
+            result = EStateMaintenance;
+            }
+        }
+
+    CleanupStack::PopAndDestroy();  // mutex Signal() and Close()
+    DLTRACEOUT(( "%d", result ));
+    return result;
+    }
+
+
+/**
+ * Instantiates the catalogs engine, using the maintenance lock to determine
+ * if instantiation is allowed.
+ */
+EXPORT_C CCatalogsEngine* CCatalogsEngine::NewLC( MCatalogsEngineObserver& aObserver )
+    {
+    DLTRACEIN(( "aObserver=%08x", &aObserver ));
+
+    // Get/create Catalogs Engine maintenance lock mutex
+    RMutex mutex;
+    GetMutexLC( mutex );
+
+    if( IsMaintenanceLockOnL() )
+        {
+        DLWARNING(( "Catalogs Engine in maintenance mode, cannot create engine instance" ));
+        DLTRACEOUT(( "LEAVE KCatalogsErrorMaintenanceMode" ));
+        User::Leave( KCatalogsErrorMaintenanceMode );
+        }
+
+    // Not in maintenance mode, ok to instantiate engine class. Do this before releasing the
+    // mutex, as this may define the maintenance lock P&S.
+    DLINFO(( "Creating ECom object with UID %08x", KCCatalogsEngineImplUid.iUid ));
+    CCatalogsEngine* object = 0;
+    TRAPD( err,
+        {
+        object = reinterpret_cast< CCatalogsEngine* >( 
+            REComSession::CreateImplementationL( 
+                KCCatalogsEngineImplUid, _FOFF(CCatalogsEngine,iDtor_ID_Key), &aObserver ) );
+        }); //TRAPD
+    DLINFO(("ECom creation err=%d",err));
+    User::LeaveIfError( err );
+    
+    DLINFO(( "ECom returned pointer %08x", object ));
+    DASSERT( object != NULL );
+
+    CleanupStack::PopAndDestroy(); // mutex signal & close
+    CleanupStack::PushL( object );
+
+    DLTRACEOUT(( "%08x", object ));
+    return object;
+    }
+
+
+EXPORT_C CCatalogsEngine* CCatalogsEngine::NewL( MCatalogsEngineObserver& aObserver )
+    {
+    DLTRACEIN(( "aObserver=%08x", &aObserver ));
+    CCatalogsEngine* engine = CCatalogsEngine::NewLC( aObserver );
+    CleanupStack::Pop();
+    DLTRACEOUT(( "%08x", engine ));
+    return engine;
+    }
+
+EXPORT_C void CCatalogsEngine::StartMaintenanceL()
+    {
+    DLTRACEIN((""));
+
+    // Get Catalogs Engine maintenance lock mutex
+    RMutex mutex;
+    GetMutexLC( mutex );
+
+    if( IsMaintenanceLockOnL() )
+        {
+        DLERROR(( "Engine already locked for maintenance mode" ));
+        DLTRACEOUT(( "LEAVE KErrAlreadyExists" ));
+        User::Leave( KErrAlreadyExists );
+        }
+
+    // Set the maintenance lock. This will send a P&S event to any existing
+    // engine instances and create a callback for the clients.
+    SetMaintenanceLockL( ETrue );
+
+    CleanupStack::PopAndDestroy();  // mutex signal & close
+    }
+
+EXPORT_C void CCatalogsEngine::EndMaintenanceL()
+    {
+    // Get Catalogs Engine maintenance lock mutex
+    DLTRACEIN((""));
+    
+    RMutex mutex;
+    GetMutexLC( mutex );
+
+    if( !IsMaintenanceLockOnL() )
+        {
+        DLERROR(( "Maintenance lock not on" ));
+        DLTRACEOUT(( "LEAVE KCatalogsErrorMaintenanceNotStarted" ));
+        User::Leave( KCatalogsErrorMaintenanceNotStarted );
+        }
+    
+    SetMaintenanceLockL( EFalse );
+
+    CleanupStack::PopAndDestroy();  // mutex signal & close
+    }
+
+#endif // CATALOGS_ECOM
+
+/**
+ * Destructor
+ */
+CCatalogsEngine::~CCatalogsEngine()
+    {
+    DLTRACEIN(( "this=%08x", this ));
+    REComSession::DestroyedImplementation( iDtor_ID_Key );
+    // Is it ok to say FinalClose() even if engine object instances exist? Should be, hope so.
+    // FinalClose not okay, from help: "It must never be called from within a plugin class destructor."
+    //DLTRACE(("FinalClose()"));
+    
+    //REComSession::FinalClose();
+    DLTRACEOUT(( "this=%08x", this ));
+    }
+
+/**
+ * Constructor
+ */
+CCatalogsEngine::CCatalogsEngine()
+    {
+    }