--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commonappservices/alarmserver/Server/Source/ASSrvAlarmStore.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,670 @@
+// Copyright (c) 1999-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 "ASSrvAlarmStore.h"
+
+// User includes
+#include "ASSrvDefs.h"
+#include "ASSrvDataPool.h"
+#include "ASSrvAlarmQueue.h"
+#include "ASSrvStaticUtils.h"
+#include "ASSrvSoundSettings.h"
+#include "ASSrvServerWideData.h"
+#include "ASSrvAlarmQueue.h"
+
+// Type definitions
+#define UNUSED_VAR(a) a = a
+
+// Constants
+const TInt KDelayInMicrosecondsBetweenFileOperations = 2000000; // 2 seconds
+const TInt KDelayInMicrosecondsBetweenFileOperationsLongDelay = 10 * 60 * 1000000; // 10 minutes, allow user time to clear disk space?
+const TInt KNumberOfAttemptsAtExternalizingFile = 5; // 5 * 2 seconds => 10 seconds
+const TInt KDelayPeriodBeforeAttemptingAnExternalize = 1000; // 1 seconds
+
+// Enumerations
+
+// Definitions
+#define __START_WITH_RESTORED_QUEUE__
+
+// Classes referenced
+
+//#define VERBOSE_DEBUG
+
+#if defined(VERBOSE_DEBUG)
+#define DEBUG_PRINT1(A) { RDebug::Print(A); }
+#define DEBUG_PRINT2(A,B) { RDebug::Print(A,B); }
+#define DEBUG_PRINT3(A,B,C) { RDebug::Print(A,B,C); }
+#else
+#define DEBUG_PRINT1(A)
+#define DEBUG_PRINT2(A,B)
+#define DEBUG_PRINT3(A,B,C)
+#endif
+
+
+
+//
+// ----> CASSrvAlarmStore (source)
+//
+
+//*************************************************************************************
+CASSrvAlarmStore::CASSrvAlarmStore(CASSrvServerWideData& aServerWideData)
+: CTimer(CActive::EPriorityIdle), iServerWideData(aServerWideData)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+
+//*************************************************************************************
+CASSrvAlarmStore::~CASSrvAlarmStore()
+ {
+#ifndef __WINC__
+ delete iBackupNotification;
+#endif
+
+ ServerWideData().Queue().NotificationPoolChangeCancel(*this);
+
+ DEBUG_PRINT1(_L("-- -- Alarm Store destructor"));
+
+ // is an externalize request still waiting?
+ if (iFlags.IsSet(ERequestExternalize))
+ {
+ Cancel();
+ // Flush current alarm queue
+ // (if this fails now there is nothing we can do about it)
+ Externalize();
+ }
+
+ // no longer interested in these events
+ ServerWideData().AnyEventManager().MASAnyEventManagerObserverRemove(*this);
+ }
+
+
+//*************************************************************************************
+void CASSrvAlarmStore::ConstructL()
+ {
+ CTimer::ConstructL();
+
+ DEBUG_PRINT1(_L("++ ++ Alarm Store ConstructL"));
+
+ TFileName name;
+ RFs& fsSession = ServerWideData().FsSession();
+ ASSrvStaticUtils::GetPrivateDirL(fsSession, name);
+
+ //Check INI file directory exists
+ TUint attribs; //Not used dummy parameter
+ TInt error = fsSession.Att(name,attribs);
+ if (error == KErrNotFound || error == KErrPathNotFound)
+ {
+ error = fsSession.MkDirAll(name);
+ }
+ User::LeaveIfError(error);
+
+ ASSrvStaticUtils::GetServerPathL(fsSession, name);
+
+#ifndef __WINC__
+ iBackupNotification = CBackupRestoreNotification::NewL(name, *this);
+#endif
+
+ // Internalize any previously persisted data
+ error = Internalize(CASSrvAlarmQueue::EStoreInternalizeStartup);
+ if (error != KErrNone)
+ {
+ error = fsSession.Delete(name);
+ if (error != KErrNotFound)
+ User::LeaveIfError(error);
+ }
+
+ // Ready to watch for "Alarm Added" and other Alarm Queue events
+ ServerWideData().Queue().NotificationPoolChangeL(*this);
+
+ // Ready to watch for Alarm Sound Intervals changing
+ ServerWideData().AnyEventManager().MASAnyEventManagerObserverAddL(*this);
+ }
+
+
+//*************************************************************************************
+CASSrvAlarmStore* CASSrvAlarmStore::NewL(CASSrvServerWideData& aServerWideData)
+ {
+ CASSrvAlarmStore* self = new(ELeave) CASSrvAlarmStore(aServerWideData);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+//
+//
+//
+
+
+
+
+//*************************************************************************************
+/**
+ * @see MASSrvAlarmQueueObserver
+ */
+void CASSrvAlarmStore::MAlarmQueueObserverHandleEvent(TASSrvAlarmQueueEvent aEvent, TAlarmId /*aAlarmId*/)
+ {
+ switch(aEvent)
+ {
+ case EASSrvAlarmQueueEventHeadItemChanged:
+ case EASSrvAlarmQueueEventAlarmAdded:
+ case EASSrvAlarmQueueEventAlarmChanged:
+ case EASSrvAlarmQueueEventAlarmDeleted:
+ // RunL will Externalize all changes in 100ms
+ ScheduleExternalizeWithRetry(100);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * @see MASSrvAnyEventObserver
+ *
+ * Facade interface that notifies observer about event. No real processing done
+ * by this object.
+ */
+void CASSrvAlarmStore::MASSrvAnyEventHandleChange(TAlarmChangeEvent aEvent, TAlarmId /*aAlarmId*/)
+ {
+ switch(aEvent)
+ {
+ case EAlarmChangeEventPlayIntervalsChanged:
+ // The sound intervals associated with sound timing have changed.
+ // RunL will Externalize all changes in 100ms
+ ScheduleExternalizeWithRetry(100);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * Internalize (non-leaving) the contents of the Alarm Server backup
+ * from the backup file.
+ */
+TInt CASSrvAlarmStore::Internalize(CASSrvAlarmQueue::TStoreOperation aInternalizeOperation)
+ {
+ TInt error = KErrNone;
+
+ DEBUG_PRINT1(_L("> Alarm Store Internalize ()"));
+
+ // tell Alarm Queue what type of Internalize to perform
+ error = ServerWideData().Queue().StartAlarmStoreOperation(aInternalizeOperation);
+
+ if (!error)
+ {
+ // don't watch for change notifications during Internalize
+ iFlags.Set(EIsInternalizing);
+
+ TRAP(error, InternalizeL());
+
+ // tell alarm queue that Internalize is complete
+ ServerWideData().Queue().EndAlarmStoreOperation(error);
+
+ // Finished Internalize, Look for notifications again, etc...
+ iFlags.Clear(EIsInternalizing);
+ }
+
+ DEBUG_PRINT2(_L("< Alarm Store Internalize - error %i"), error);
+
+ return error;
+ }
+
+
+//*************************************************************************************
+/**
+ * Internalize the contents of the Alarm Server backup
+ * from the backup file.
+ */
+void CASSrvAlarmStore::InternalizeL()
+ {
+ RStoreReadStream stream;
+ CDirectFileStore* store = OpenStoreLC(EFileRead);
+ CStreamDictionary* dictionary = OpenDictionaryLC(*store);
+
+ // Open the alarm queue stream & internalize
+#ifdef __START_WITH_RESTORED_QUEUE__
+ OpenStreamLC(*store, *dictionary, KAlarmStoreStreamUidQueue, stream);
+ stream >> ServerWideData().Queue();
+ CleanupStack::PopAndDestroy(&stream);
+
+ // Open the alarm data stream & internalize
+ OpenStreamLC(*store, *dictionary, KAlarmStoreStreamUidData, stream);
+ stream >> ServerWideData().DataPool();
+ CleanupStack::PopAndDestroy(&stream);
+#endif
+
+ // Open the sound settings stream & internalize
+ OpenStreamLC(*store, *dictionary, KAlarmStoreStreamUidSoundSettings, stream);
+ stream >> ServerWideData().SoundSettings();
+ CleanupStack::PopAndDestroy(&stream);
+
+#ifdef SYMBIAN_SKIPPED_CALENDAR_ALARMS
+ // Open the missed alarm data stream & internalize
+ OpenStreamLC(*store, *dictionary, KAlarmStoreStreamUidEnvironmentChangeData, stream);
+ ServerWideData().Queue().InternalizeLastAlarmedInstanceParamsL(stream);
+ CleanupStack::PopAndDestroy(&stream);
+#endif
+
+ // Tidy up
+ CleanupStack::PopAndDestroy(2, store);
+ }
+
+//*************************************************************************************
+/**
+ * Externalize (non-leaving) the contents of the Alarm Server backup
+ * to the backup file.
+ */
+TInt CASSrvAlarmStore::ExternalizeIfRequested()
+ {
+ TInt error = KErrNone;
+
+ DEBUG_PRINT2(_L("= Alarm Store Externalize If Requested (%u)"), iFlags.IsSet(ERequestExternalize));
+
+ if (iFlags.IsSet(ERequestExternalize))
+ {
+ // Don't RunL
+ Cancel();
+
+ error = Externalize();
+ }
+
+ return error;
+ }
+
+
+//*************************************************************************************
+/**
+ * Externalize (non-leaving) the contents of the Alarm Server backup
+ * to the backup file.
+ */
+TInt CASSrvAlarmStore::Externalize()
+ {
+ TInt error = KErrNone;
+
+#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT
+ if (!iServerWideData.ServerIsReadOnly())
+ {
+#endif
+ DEBUG_PRINT1(_L("> Alarm Store Externalize"));
+
+ // tell Alarm Queue what type of Store operation we want to perform
+ error = ServerWideData().Queue().StartAlarmStoreOperation(CASSrvAlarmQueue::EStoreExternalize);
+
+ if (!error)
+ {
+ TRAP(error, ExternalizeL());
+
+ // tell alarm queue that Externalize is complete
+ ServerWideData().Queue().EndAlarmStoreOperation(error);
+ }
+
+ DEBUG_PRINT2(_L("< Alarm Store Externalize - error %i"), error);
+#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT
+ }
+#endif
+
+ return error;
+ }
+
+
+//*************************************************************************************
+/**
+ * Externalize the contents of the Alarm Server backup
+ * to the backup file.
+ */
+void CASSrvAlarmStore::ExternalizeL()
+ {
+ TStreamId streamId;
+ RStoreWriteStream stream;
+ CStreamDictionary* dictionary = CStreamDictionary::NewLC();
+
+ CDirectFileStore* store = OpenStoreLC(EFileWrite | EFileShareExclusive);
+
+ // Create the alarm queue stream & externalize
+ streamId = stream.CreateLC(*store);
+ stream << ServerWideData().Queue();
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ dictionary->AssignL(KAlarmStoreStreamUidQueue, streamId);
+
+ // Create the alarm data queue & externalize
+ streamId = stream.CreateLC(*store);
+ stream << ServerWideData().DataPool();
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ dictionary->AssignL(KAlarmStoreStreamUidData, streamId);
+
+ // Create the alarm data queue & externalize
+ streamId = stream.CreateLC(*store);
+ stream << ServerWideData().SoundSettings();
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ dictionary->AssignL(KAlarmStoreStreamUidSoundSettings, streamId);
+
+#ifdef SYMBIAN_SKIPPED_CALENDAR_ALARMS
+ // Create the missed alarm data stream & externalize
+ streamId = stream.CreateLC(*store);
+ ServerWideData().Queue().ExternalizeLastAlarmedInstanceParamsL(stream);
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ dictionary->AssignL(KAlarmStoreStreamUidEnvironmentChangeData, streamId);
+#endif
+
+ // Create root stream
+ streamId = stream.CreateLC(*store);
+ stream << *dictionary;
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ store->SetRootL(streamId);
+ store->CommitL();
+
+ // clear Externalize request flag now, so another can be requested
+ iFlags.Clear(ERequestExternalize);
+
+ // Tidy up
+ CleanupStack::PopAndDestroy(2, dictionary);
+ }
+
+
+//*************************************************************************************
+/**
+ * Open the backup store (AlarmServer.ini) using the specified
+ * file mode.
+ *
+ * @return A file store object which encapsulates the backup store.
+ */
+CDirectFileStore* CASSrvAlarmStore::OpenStoreLC(TUint aMode) const
+ {
+ CDirectFileStore* store = OpenStoreL(aMode);
+
+ CleanupStack::PushL(store);
+ //
+ return store;
+ }
+
+
+/**
+ * Open the backup store (AlarmServer.ini) using the specified
+ * file mode.
+ *
+ * @return A file store object which encapsulates the backup store.
+ */
+CDirectFileStore* CASSrvAlarmStore::OpenStoreL(TUint aMode) const
+ {
+ RFs& fsSession = ServerWideData().FsSession();
+ TFileName fileName;
+ ASSrvStaticUtils::GetServerPathL(fsSession, fileName);
+
+ CDirectFileStore* store = NULL;
+ TInt error = KErrNone;
+ //
+ if (aMode == EFileRead)
+ {
+ // First try to open the store. If opening fails, then we
+ // replace the store with a blank one.
+ TRAP(error, store = CDirectFileStore::OpenL(fsSession, fileName, aMode));
+ }
+ //
+ if (!store || error != KErrNone)
+ {
+ store = CDirectFileStore::ReplaceLC(fsSession, fileName, aMode);
+ //
+ const TUidType type(KDirectFileStoreLayoutUid, KAlarmStoreUid, KNullUid);
+ store->SetTypeL(type);
+ //
+ CleanupStack::Pop(store);
+ }
+ //
+ return store;
+ }
+
+
+//*************************************************************************************
+/**
+ * Restore the root stream dictionary from the specified store
+ *
+ * @return A stream dictionary object on the cleanup stack
+ */
+CStreamDictionary* CASSrvAlarmStore::OpenDictionaryLC(CPersistentStore& aStore) const
+ {
+ const TStreamId rootId = aStore.Root();
+ //
+ CStreamDictionary* dictionary = CStreamDictionary::NewLC();
+ RStoreReadStream stream;
+ stream.OpenLC(aStore, rootId);
+ stream >> *dictionary;
+ CleanupStack::PopAndDestroy(&stream);
+ //
+ return dictionary;
+ }
+
+
+//*************************************************************************************
+/**
+ * Open the specified stream in the store
+ */
+void CASSrvAlarmStore::OpenStreamLC(CPersistentStore& aStore, CStreamDictionary& aDictionary, TUid aStreamUid, RStoreReadStream& aStream) const
+ {
+ const TStreamId streamId = aDictionary.At(aStreamUid);
+ aStream.OpenLC(aStore, streamId);
+ }
+
+
+//*************************************************************************************
+/**
+ * Retry a previously requested backup operation
+ */
+void CASSrvAlarmStore::RetryStoreOperation()
+ {
+ if (iFlags.IsSet(ERequestExternalize) && !IsActive())
+ {
+ // can RunL now
+ After(0);
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * @see CActive
+ */
+void CASSrvAlarmStore::RunL()
+ {
+ TInt error = iStatus.Int();
+
+ // operation isn't cancelled
+ if (error == KErrNone)
+ {
+ // task : Externalize
+ if (iFlags.IsSet(ERequestExternalize))
+ {
+ // Try to Externalize
+ error = Externalize();
+
+ if (error < KErrNone)
+ {
+ ++iNumberOfAttemptedRetries;
+
+ // check retries, and reschedule
+ if (iNumberOfAttemptedRetries == KNumberOfAttemptsAtExternalizingFile)
+ {
+ // Try one last time. Wait for 10 mins and then attempt operation again.
+ // After that, give up.
+ //
+ // Possible reasons for entering this state:
+ //
+ // Low disk space, low memory, corrupt file system, etc etc. Don't think
+ // its acceptable to panic - operation should be failed gracefully.
+ After(KDelayInMicrosecondsBetweenFileOperationsLongDelay);
+ }
+ else if (iNumberOfAttemptedRetries < KNumberOfAttemptsAtExternalizingFile)
+ {
+ // Try again after the delay
+ After(KDelayInMicrosecondsBetweenFileOperations);
+ }
+ else
+ {
+ // Tried max number of times already. Give up.
+ iFlags.Clear(ERequestExternalize);
+ }
+ }
+
+ }
+ }
+ }
+
+
+//*************************************************************************************
+
+#ifndef __WINC__
+void CASSrvAlarmStore::ScheduleExternalizeWithRetry(TUint aTimeMS)
+#else
+void CASSrvAlarmStore::ScheduleExternalizeWithRetry(TUint /*aTimeMS*/)
+#endif
+ {
+ // make sure change isn't due to Internalize
+ if (iFlags.IsClear(EIsInternalizing))
+ {
+ DEBUG_PRINT2(_L("*** Schedule Externalize - IsActive() = %u"), IsActive());
+
+ iFlags.Set(ERequestExternalize);
+ iNumberOfAttemptedRetries = 0;
+
+#ifndef __WINC__
+ // set the time to RunL iff not already set to run
+ // check that no Backup or Restore is in progress,
+ if (!iBackupNotification->BackupInProgress() &&
+ !iBackupNotification->RestoreInProgress()&& !IsActive())
+ {
+ // schedule the actual Externalize
+ After(aTimeMS * 1000);
+ }
+#endif
+ }
+ }
+
+
+//*************************************************************************************
+/**
+ * @see CActive
+ */
+TInt CASSrvAlarmStore::RunError(TInt /*aError*/)
+ {
+ return KErrNone;
+ }
+
+
+//*************************************************************************************
+#ifndef __WINC__
+
+/**
+ * @see MBackupRestoreNotificationObserver
+ */
+
+void CASSrvAlarmStore::BackupBeginningL()
+ {
+ DEBUG_PRINT1(_L("-> Alarm Store => Backup Beginning"));
+ StartOfBackupOrRestoreL(CASSrvAlarmQueue::EStoreBackup);
+ }
+
+void CASSrvAlarmStore::BackupCompletedL()
+ {
+ // End of Backup
+ DEBUG_PRINT1(_L("-> Alarm Store => Backup Ended"));
+
+ // Backup server was reading from the alarm file so
+ // tell alarm queue that Backup is complete
+ ServerWideData().Queue().EndAlarmStoreOperation(KErrNone);
+
+ // In case Store has been waiting for backup to finish. Now
+ // attempt to perform deferred operation.
+ RetryStoreOperation();
+ }
+
+void CASSrvAlarmStore::RestoreBeginningL()
+ {
+ // Restore is starting
+ DEBUG_PRINT1(_L("-> Alarm Store => Restore Beginning"));
+ StartOfBackupOrRestoreL(CASSrvAlarmQueue::EStoreRestore);
+}
+
+void CASSrvAlarmStore::RestoreCompletedL(TInt aRestoreResult)
+ {
+ DEBUG_PRINT1(_L("-> Alarm Store => Restore Ended"));
+
+ // If the Backup server successfully wrote to the alarm file, then we should
+ // read its contents and restore all alarm data based upon it.
+ if (aRestoreResult == KErrNone)
+ {
+ DEBUG_PRINT1(_L("-- End of Restore ... EEnd"));
+ // Any error during Internalize must be pretty severe so catch it and leave.
+ // NB Internalize calls ServerWideData().Queue().EndAlarmStoreOperation();
+ User::LeaveIfError(Internalize(CASSrvAlarmQueue::EStoreInternalizeRestore));
+ }
+ else
+ {
+ DEBUG_PRINT1(_L("-- end of Restore ... EAbort"));
+
+ ServerWideData().Queue().EndAlarmStoreOperation(KErrGeneral);
+
+ // we don't know what state the AlarmServer.Ini file is in
+ // so want an Externalize() to happen soon
+ ScheduleExternalizeWithRetry(KDelayPeriodBeforeAttemptingAnExternalize);
+ }
+ }
+
+#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT
+void CASSrvAlarmStore::MHandleSystemStateChange(TState aState)
+ {
+ if (aState == EShutdown)
+ {
+ ExternalizeIfRequested();
+ }
+ }
+#endif
+
+void CASSrvAlarmStore::StartOfBackupOrRestoreL(CASSrvAlarmQueue::TStoreOperation aStoreOperation)
+ {
+ // Flush any 'scheduled' Externalize before Restore
+ ExternalizeIfRequested();
+
+ // tell Alarm Queue what type of Store is wanted
+ User::LeaveIfError(ServerWideData().Queue().StartAlarmStoreOperation(aStoreOperation));
+ }
+#endif // #ifndef __WINC__