diff -r 000000000000 -r ba25891c3a9e ncdengine/engine/src/catalogsengine.cpp --- /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 +#include +#include + +#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() + { + }