--- /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 <logcli.h>
+#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<TLogBackupNotificationEntry> 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; i<count; i++)
+ {
+ const TLogBackupNotificationEntry& entry = iObservers[i];
+ if (&aObserver == &entry.iObserver)
+ {
+ iObservers.Remove(i);
+ return;
+ }
+ }
+ }
+
+MLogServBackupInterface::TLogServBackupState CLogServBackupManager::BIState() const
+ {
+ return iState;
+ }
+
+TInt CLogServBackupManager::BIErrorValueForCurrentState() const
+ {
+ TInt error = KErrNone;
+ switch(BIState())
+ {
+ case ELogServBackupStateIdle:
+ error = KErrNone;
+ break;
+ case ELogServBackupStateBackupInProgress:
+ error = KErrAccessDenied;
+ break;
+ }
+ //
+ LOGTEXT2("CLogServBackupManager::BIErrorValueForCurrentState() = %d", error);
+ return error;
+ }
+
+void CLogServBackupManager::BISetDatabaseNameL(const TDesC& aDatabaseName)
+ {
+#ifdef LOGGING_ENABLED
+ LOGTEXT3("CLogServBackupManager::BISetDatabaseNameL(%S, isActive: %d)", &aDatabaseName, IsActive());
+ if (iDatabaseName)
+ {
+ LOGTEXT2("CLogServBackupManager::BISetDatabaseNameL() - currently registered database filename is: %S", iDatabaseName);
+ }
+ else
+ {
+ LOGTEXT("CLogServBackupManager::BISetDatabaseNameL() - no file registered with backup interface yet");
+ }
+#endif
+
+ Cancel();
+
+ HBufC* databaseName = aDatabaseName.AllocLC();
+
+ // If we haven't already created a backup observer, then we need
+ // to kick the object back into life again.
+ if (!iBackup)
+ {
+ LOGTEXT("CLogServBackupManager::BISetDatabaseNameL() - no backup session created");
+
+ // Try and create backup interface synchronously first of all, if that fails
+ // then construct as an idle operation
+ TRAPD(err, iBackup = CreateBackupL(*databaseName));
+
+ LOGTEXT2("CLogServBackupManager::BISetDatabaseNameL() - backup session creation error: %d", err);
+ if (err != KErrNone)
+ After(0);
+ }
+ else if (iDatabaseName->Compare(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<count; i++)
+ {
+ TLogBackupNotificationEntry& entry = iObservers[i];
+ entry.iObserver.BOHandleEventL(aEvent);
+ }
+ }
+ break;
+ case MLogServBackupObserver::EBackupEnded:
+ {
+ // Update our state
+ iState = ELogServBackupStateIdle;
+
+ // Notify
+ for(TInt i=count-1; 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;
+ }