--- /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()
+ {
+ }