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