diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/LogServ/src/LogServBackupManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loggingservices/eventlogger/LogServ/src/LogServBackupManager.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,350 @@ +// Copyright (c) 2002-2009 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: +// + +#include "LogServBackupManager.h" + +// User includes +#include +#include "logservpanic.h" + +// Constants +const TInt KTimerDelay = 10000000; // 10 seconds + + +///////////////////////////////////////////////////////////////////////////////////////// +// -----> CLogServBackupManager (source) +///////////////////////////////////////////////////////////////////////////////////////// + +CLogServBackupManager::CLogServBackupManager(TInt aPriority) +: CTimer(aPriority) + { + CActiveScheduler::Add(this); + } + +CLogServBackupManager::~CLogServBackupManager() + { + __ASSERT_DEBUG(iObservers.Count() == 0, Panic(ELogBackupObserversStillRegistered)); + Cancel(); + + // Unregister ourselves with backup server + if (iBackup) + { + if (iDatabaseName) + iBackup->DeregisterFile(*iDatabaseName); + delete iBackup; + } + delete iDatabaseName; + iObservers.Close(); + } + +void CLogServBackupManager::ConstructL() + { + CTimer::ConstructL(); + } + +CLogServBackupManager* CLogServBackupManager::NewL(TInt aPriority) + { + CLogServBackupManager* self = new(ELeave) CLogServBackupManager(aPriority); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +void CLogServBackupManager::BIObserverAddL(MLogServBackupObserver& aObserver, TLogServBackupPriority aPriority) + { + LOGTEXT2("CLogServBackupManager::BIObserverAddL(aPriority=%d)", aPriority); + TLogBackupNotificationEntry entry(aObserver, aPriority); + + // Create orderer which ensures that we place the objects in priority ascending order (i.e. + // higher priority gets notified first). + TLinearOrder orderer(CompareEntries); + const TInt error = iObservers.InsertInOrderAllowRepeats(entry, orderer); + User::LeaveIfError(error); + + LOGTEXT("CLogServBackupManager::BIObserverAddL() - end"); + } + +void CLogServBackupManager::BIObserverRemove(MLogServBackupObserver& aObserver) +// +// Removes an observer from the notification queue +// + { + const TInt count = iObservers.Count(); + for(TInt i=0; iCompare(aDatabaseName) != KErrNone) + { + LOGTEXT3("CLogServBackupManager::BISetDatabaseNameL() - database filename changed from %S to %S", &iDatabaseName, &aDatabaseName); + + // De register the old, register the new + iBackup->DeregisterFile(*iDatabaseName); + iBackup->RegisterFileL(aDatabaseName, *this); + + LOGTEXT("CLogServBackupManager::BISetDatabaseNameL() - database re-registration complete"); + } + + + delete iDatabaseName; + iDatabaseName = databaseName; + CleanupStack::Pop(databaseName); + + LOGTEXT("CLogServBackupManager::BISetDatabaseNameL() - end"); + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +void CLogServBackupManager::RunL() +// +// This method does two things +// +// 1) Keeps trying to create a backup object - which may fail on device +// bootup until the ui framework starts the backup server. +// +// 2) Handles the case where the server fails to restart correctly after a backup - it keeps trying +// + { + LOGTEXT2("CLogServBackupManager::RunL(%d)", iStatus.Int()); + + if (!iBackup) + { + LOGTEXT("CLogServBackupManager::RunL() - trying to create backup object"); + + // Keep trying to create backup object + iBackup = CreateBackupL(*iDatabaseName); + + LOGTEXT("CLogServBackupManager::RunL() - backup object created okay"); + } + else + { + // This branch is executed if we failed to create the backup object on our first + // attempt in BISetDatabaseNameL + LOGTEXT("CLogServBackupManager::RunL() - notifying observers about dummy backup ended event"); + NotifyObservers(MLogServBackupObserver::EBackupEnded); + } + + LOGTEXT("CLogServBackupManager::RunL() - end"); + } + +TInt CLogServBackupManager::RunError(TInt aError) + { + (void) aError; + LOGTEXT2("CLogServBackupManager::RunError(%d)", aError); + + // Make sure we don't leak anything, pretend the backup started again - won't fail + if (iBackup) + NotifyObservers(MLogServBackupObserver::EBackupStarting); + + After(KTimerDelay); + + LOGTEXT("CLogServBackupManager::RunError() - end"); + return KErrNone; + } + +TInt CLogServBackupManager::NotifyObservers(MLogServBackupObserver::TLogServBackupEvent aEvent) +// +// Notify observers of the event. Assumes event queue correctly ordered. +// + { + const TInt count = iObservers.Count(); + LOGTEXT3("CLogServBackupManager::NotifyObservers(aEvent = %d) - %d observers", aEvent, count); + + // Depending on the event type, we have to reverse the order of notification. + // I wish it was possible to do this in a more elegant way... hmm... pointers + // to member functions?... + + TInt error = KErrNone; + TRAP(error, + // + switch(aEvent) + { + case MLogServBackupObserver::EBackupStarting: + { + // Update our state + iState = ELogServBackupStateBackupInProgress; + + // Notify + for(TInt i=0; i=0; i--) + { + TLogBackupNotificationEntry& entry = iObservers[i]; + entry.iObserver.BOHandleEventL(aEvent); + } + } + break; + } + ); + + LOGTEXT("CLogServBackupManager::NotifyObservers() - end"); + return error; + } + +void CLogServBackupManager::ChangeFileLockL(const TDesC& aFileName, TFileLockFlags aFlags) + { + LOGTEXT3("CLogServBackupManager::ChangeFileLockL(%S, aFlags = %d)", &aFileName, aFlags); + +#ifdef LOGGING_ENABLED + if (aFlags & (MBackupObserver::EReleaseLockReadOnly | MBackupObserver::EReleaseLockNoAccess)) + { + LOGTEXT("CLogServBackupManager::ChangeFileLockL() - Backup is STARTING"); + } + else + { + LOGTEXT("CLogServBackupManager::ChangeFileLockL() - Backup is ENDING"); + } +#endif + + Cancel(); + + // This probably won't ever happen + if (iDatabaseName->Compare(aFileName) != 0) + { + LOGTEXT("CLogServBackupManager::ChangeFileLockL() - Notification from backup server about the wrong file!"); + User::Leave(KErrNotFound); + } + + // Work out type of backup event + MLogServBackupObserver::TLogServBackupEvent event = MLogServBackupObserver::EBackupEnded; + if (aFlags & (MBackupObserver::EReleaseLockReadOnly | MBackupObserver::EReleaseLockNoAccess)) + event = MLogServBackupObserver::EBackupStarting; + + // Notify observers + const TInt error = NotifyObservers(event); + LOGTEXT2("CLogServBackupManager::ChangeFileLockL() - notifying observers error: %d", error); + + // Shouldn't be any problems when notifying observers + __ASSERT_DEBUG(!(event == MLogServBackupObserver::EBackupStarting && error != KErrNone), Panic(ELogStartBackupFailure)); + + // Handle failure to restart the server after a backup + if (error && (event == MLogServBackupObserver::EBackupEnded)) + { + LOGTEXT("CLogServBackupManager::ChangeFileLockL() - Kicking off server objects again after backup completed (and there was an error)"); + + // Make sure we don't leak anything, pretend the backup started again - won't fail + Cancel(); + NotifyObservers(MLogServBackupObserver::EBackupStarting); + After(KTimerDelay); + } + + LOGTEXT("CLogServBackupManager::ChangeFileLockL() - end"); + } + +CBaBackupSessionWrapper* CLogServBackupManager::CreateBackupL(const TDesC& aLogDatabaseFileName) + { + LOGTEXT("CLogServBackupManager::CreateBackupL()"); + + // Create backup session + CBaBackupSessionWrapper* backup = CBaBackupSessionWrapper::NewL(); + CleanupStack::PushL(backup); + + // Register with the backup server + backup->RegisterFileL(aLogDatabaseFileName, *this); + + // All done + CleanupStack::Pop(backup); + + LOGTEXT("CLogServBackupManager::CreateBackupL() - end"); + return backup; + } + +TInt CLogServBackupManager::CompareEntries(const TLogBackupNotificationEntry& aLeft, const TLogBackupNotificationEntry& aRight) + { + if (aLeft.iPriority == aRight.iPriority) + return 0; + else if (aLeft.iPriority > aRight.iPriority) // Not what you might expect since higher priority must go first + return -1; + return 1; + }