--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/taskscheduler/SCHSVR/SCHMAN.CPP Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,912 @@
+// Copyright (c) 2004-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:
+//
+
+// System includes
+#include <bacntf.h>
+
+// User includes
+#include "SCHMAN.H"
+#include "SchTimer.h"
+#include "SchLogger.h"
+#include "SCHEDULE.H"
+#include "SCHCLI.H"
+#include "SCHSTORE.H"
+#include <schtask.h>
+#include "SCHLOG.h"
+
+// Constants
+const TInt KMinScheduleId = 0;
+const TInt KMaxSchedules = 25000;
+
+//Command line argument
+_LIT(KCommandLine, "SYSSTARTSCHEXE");
+
+//SID of SysStart
+const TInt KSysStartSID = 0x10205C44;
+
+
+#define UNUSED_VAR(a) a = a
+
+//
+// Construction/Destruction functions
+//
+
+CTaskScheduler::CTaskScheduler()
+: iSchedules(CSchedule::Offset()),
+ iClients(CClientProxy::Offset()),
+ iStartupStatePassNonCritical(EFalse)
+ {
+ }
+
+CTaskScheduler::~CTaskScheduler()
+ {
+ if (iBackupNotification)
+ {
+ iBackupNotification->DeRegisterBackupOperationObserver(*this);
+ }
+ delete iBackupNotification;
+ delete iBackupManager;
+ delete iNotifier;
+ delete iScheduleCriteriaManager;
+ delete iSchLogManager;
+
+ //remove clients and schedules as well!!
+ TDblQueIter<CClientProxy> clientIter(iClients);
+
+ clientIter.SetToFirst();
+ CClientProxy* client=NULL;
+ while ((client=clientIter++)!=NULL)
+ {
+ client->Remove();
+ delete client;
+ }
+
+ TSglQueIter<CSchedule> schedIter(iSchedules);
+
+ schedIter.SetToFirst();
+ CSchedule* schedule=NULL;
+ while ((schedule=schedIter++)!=NULL)
+ {
+ iSchedules.Remove(*schedule);
+ delete schedule;
+ }
+ }
+
+void CTaskScheduler::ConstructL()
+ {
+ LOGSTRING("CTaskScheduler::ConstructL - Creating new schedule server log entry");
+
+ User::LeaveIfError(iFsSession.Connect());
+ iBackupManager = new(ELeave) CSchBackupManager(iFsSession);
+ iBackupManager->ConstructL();
+
+ iNotifier = CEnvironmentChangeNotifier::NewL(CActive::EPriorityHigh, TCallBack(EnvironmentChanged, this));
+ iNotifier->Start();
+
+ iScheduleCriteriaManager = CScheduleCriteriaManager::NewL(*this);
+
+ iSchLogManager = CSchLogManager::NewL(iFsSession);
+
+ LOGSTRING("CTaskScheduler::ConstructL - Restoring clients and schedules");
+ TRAPD(err, iBackupManager->RestoreL(iClients, iSchedules,*iSchLogManager));
+ if (err != KErrNone) // the file's corrupt or something...
+ {
+ LOGSTRING2("CTaskScheduler::ConstructL - had to create new store because of error: %d", err);
+ iBackupManager->CreateEmptyBackupL();
+ }
+
+ //checking the SID of the process which started the Task scheduler
+ if (User::CreatorSecureId() == KSysStartSID)
+ {
+ TInt argLen = User::CommandLineLength();
+ if (argLen)
+ {
+ HBufC* arg = HBufC::NewLC(argLen);
+ TPtr argPtr = arg->Des();
+ User::CommandLine(argPtr);
+ argPtr.UpperCase();
+
+ //Checking Comman dLine arg passed to it is same as in SSCForStartupMode0.rss
+ //and checking for persisted schedules
+ if((argPtr.Compare(KCommandLine) == 0) && iSchedules.IsEmpty())
+ {
+ //if no schedule leave
+ User::Leave(KErrNone);
+ }
+ CleanupStack::PopAndDestroy(arg);
+ }
+ }
+
+ // Each client now contains a list of associated tasks. We need
+ // to now associate those tasks with specific schedules
+ CClientProxy* client;
+ TDblQueIter<CClientProxy> clientIter(iClients);
+ clientIter.SetToFirst();
+ while ((client = clientIter++) != NULL)
+ {
+ // Fetch an iterator for each task owned by this client
+ CScheduledTask* task;
+ TDblQueIter<CScheduledTask> taskIterator = client->TaskIterator();
+ taskIterator.SetToFirst();
+
+ // Iterate through all the tasks owned by this client, trying to find
+ // the corresponding schedules.
+ while ((task = taskIterator++) != NULL)
+ {
+ CSchedule* schedule = NULL;
+ schedule = Find(task->ScheduleId());
+ if (schedule)
+ {
+ TScheduledTask* taskRef = new(ELeave) TScheduledTask(*task,*client);
+ schedule->AddTask(*taskRef);
+ }
+ }
+ }
+ iBackupNotification = CBaBackupSessionWrapper::NewL();
+ iBackupNotification->RegisterBackupOperationObserverL(*this);
+ }
+
+CTaskScheduler* CTaskScheduler::NewL()
+ {
+ CTaskScheduler* self = CTaskScheduler::NewLC();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CTaskScheduler* CTaskScheduler::NewLC()
+ {
+ CTaskScheduler* self = new(ELeave) CTaskScheduler();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+//
+// Client, Schedule and Task functions
+//
+
+CClientProxy* CTaskScheduler::AddClientL(const TDesC& aFilename, TInt aPriority)
+ {
+ //check we don't already have a client that will do...
+ TDblQueIter<CClientProxy> clientIter(iClients);
+ clientIter.SetToFirst();
+ CClientProxy* client=NULL;
+ while ((client=clientIter++)!=NULL)
+ {
+ if (client->IsEqual(aFilename, aPriority))
+ return client;
+ }
+ client = CClientProxy::NewL(iFsSession, aFilename, aPriority,*iSchLogManager);
+ iClients.Add(*client);
+ return client;
+ }
+
+void CTaskScheduler::AddScheduleL(CSchedule& aSchedule)
+ {
+ LOGSTRING3("CTaskScheduler::AddScheduleL - schedule: %S, %d", &aSchedule.Name(), aSchedule.Id());
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationAdd, aSchedule);
+ iSchedules.AddLast(aSchedule);
+ LOGSTRING("CTaskScheduler::AddScheduleL - schedule added");
+ }
+
+void CTaskScheduler::EditScheduleL(TInt aScheduleHandle, CArrayFixFlat<TScheduleEntryInfo2>& aEntryList)
+ {
+ CSchedule* schedule = FindL(aScheduleHandle);
+
+ // remove schedule from condition manager before replacing entries to ensure
+ // its deleted properly.
+ iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
+ schedule->ReplaceEntriesL(aEntryList);
+
+ TRAPD(err, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule));
+ if(err)
+ {
+ schedule->RemoveEntries();
+ User::Leave(err);
+ }
+ // recalculate due time only if schedule is enabled and has tasks to run
+ if (IsScheduleReadyForUpdate(*schedule))
+ {
+ iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
+ }
+ }
+
+void CTaskScheduler::DoEditScheduleL(CSchedule& aSchedule,
+ CArrayFixFlat<TTaskSchedulerCondition>& aConditionList,
+ const TTsTime& aDefaultTime)
+ {
+ aSchedule.ReplaceConditionsL(aConditionList);
+
+ //Default Time is represented by a single entry class
+ CArrayFixFlat<TScheduleEntryInfo2>* entries
+ = new(ELeave) CArrayFixFlat<TScheduleEntryInfo2>(1);
+ CleanupStack::PushL(entries);
+ TScheduleEntryInfo2 info;
+ info.SetStartTime(aDefaultTime);
+ info.SetInterval(1);
+ info.SetIntervalType(EDaily);
+ //validityperiod of 24 hours will ensure task is always run
+ info.SetValidityPeriod(60*24);
+ entries->AppendL(info);
+ aSchedule.ReplaceEntriesL(*entries);
+ CleanupStack::Pop(entries);
+
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, aSchedule);
+ }
+
+void CTaskScheduler::EditScheduleL(TInt aScheduleHandle,
+ CArrayFixFlat<TTaskSchedulerCondition>& aConditionList,
+ const TTsTime& aDefaultTime)
+ {
+ CSchedule* schedule = FindL(aScheduleHandle);
+
+ // remove schedule from condition manager before replacing entries to ensure
+ // its deleted properly.
+ iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
+
+ TRAPD(err, DoEditScheduleL(*schedule, aConditionList, aDefaultTime));
+ if(err)
+ {
+ schedule->RemoveEntries();
+ schedule->RemoveConditions();
+ User::Leave(err);
+ }
+
+ // recalculate due time only if schedule is enabled and has tasks to run
+ if (IsScheduleReadyForUpdate(*schedule))
+ {
+ iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
+ }
+ }
+
+void CTaskScheduler::RemoveScheduleL(TInt aHandle)
+ {
+ CSchedule* schedule = FindL(aHandle);
+ LOGSTRING3("CTaskScheduler::RemoveScheduleL - schedule: %S, %d", &schedule->Name(), schedule->Id());
+ if (!schedule->HasTasks())
+ {
+ LOGSTRING("CTaskScheduler::RemoveScheduleL - schedule doesn't have any tasks, removing");
+ //remove schedule from timer
+ iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
+ DoRemoveL(schedule);
+ }
+ else
+ {
+ // Can't delete a schedule which has tasks
+ LOGSTRING("CTaskScheduler::RemoveScheduleL - schedule has tasks, can't delete");
+ User::Leave(KErrArgument);
+ }
+ }
+
+void CTaskScheduler::DisableScheduleL(TInt aHandle)
+ {
+ CSchedule* schedule = FindL(aHandle);
+ schedule->SetEnabled(EFalse);
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule);
+ //remove schedule from timer as its disabled
+ iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
+ }
+
+void CTaskScheduler::EnableScheduleL(TInt aHandle)
+ {
+ CSchedule* schedule = FindL(aHandle);
+ schedule->SetEnabled(ETrue);
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule);
+
+ // recalculate due time only if schedule has tasks to run
+ if ( IsScheduleReadyForUpdate(*schedule))
+ {
+ iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
+ }
+ }
+
+void CTaskScheduler::ScheduleTaskL(CSchedule& aSchedule, CClientProxy& aClient)
+ {
+ // Backup the task
+ if (aSchedule.Persists())
+ {
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, aClient);
+ }
+ // if schedule is enabled then add schedule to timer.
+ if (aSchedule.Enabled() && IsStartupStateNonCritical())
+ {
+ iScheduleCriteriaManager->ReplaceScheduleL(aSchedule);
+ }
+ }
+
+void CTaskScheduler::DeleteTaskL(TInt aScheduleHandle, TInt aTaskHandle)
+ {
+ CSchedule* schedule = FindL(aScheduleHandle);
+
+ TScheduledTask* task = schedule->Task(aTaskHandle);
+ if (!task)
+ {
+ LOGSTRING("CTaskScheduler::DeleteTaskL - task wasn't found");
+ User::Leave(KErrNotFound);
+ }
+
+ const CClientProxy& clientForTask = task->Client();
+
+ // This deletes the task and removes the CScheduledTask
+ // from the CClientProxy's queue of tasks
+ task->RemoveInfo();
+
+ // This deletes the TScheduledTask defined above and removes it
+ // from CSchedule's queue of TScheduledTask's.
+ schedule->RemoveTask(task);
+ if (!schedule->HasTasks()) //i.e. it was the last task
+ {
+ LOGSTRING("CTaskScheduler::DeleteTaskL - schedule doesn't have any more tasks left");
+ //remove scheule from timer as there are no more tasks
+ iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
+ // If the schedule isn't persistent then we delete it (transient schedules only
+ // have one task).
+ if (!schedule->Persists())
+ DoRemoveL(schedule);
+ else
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, clientForTask);
+ }
+ else
+ {
+ // Backup the changes to the tasks. Although we are deleting a task, we are not actually
+ // deleting the client, so this is actually an edit operation.
+ if (schedule->Persists())
+ iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, clientForTask);
+ }
+ }
+
+//
+// Utility Functions
+//
+
+TInt CTaskScheduler::GenerateId()
+ {
+ TInt id = KMinScheduleId;
+ CSchedule* schedule = Find(id);
+ while (schedule!=NULL)
+ {
+ id+=KScheduleIdDifferential;//=10 000
+ if ((id/KScheduleIdDifferential) > KMaxSchedules)
+ return KErrOverflow;
+ schedule = Find(id);
+ }
+ return id;
+ }
+
+void CTaskScheduler::DoRemoveL(CSchedule* aSchedule)
+ {
+ TRAPD(err, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationDelete, *aSchedule));
+ if (err < KErrNone && err != KErrNotFound)
+ User::Leave(err);
+ iSchedules.Remove(*aSchedule);
+ delete aSchedule;
+ aSchedule = NULL;
+ }
+
+CSchedule* CTaskScheduler::FindL(TInt aHandle)
+ {
+ CSchedule* schedule = Find(aHandle);
+ if (!schedule)
+ User::Leave(KErrNotFound);
+ return schedule;
+ }
+
+CSchedule* CTaskScheduler::Find(TInt aHandle)
+ {
+ TSglQueIter<CSchedule> scheduleIter(iSchedules);
+ scheduleIter.SetToFirst();
+ CSchedule* schedule;
+ while ((schedule = scheduleIter++)!=NULL)
+ {
+ if (schedule->Id() == aHandle)
+ return schedule;
+ }
+ return NULL;
+ }
+
+// If aRefArray is NULL then only count it returned.
+TInt CTaskScheduler::GetScheduleRefsL(CArrayFixFlat<TSchedulerItemRef>* aRefArray,
+ TScheduleFilter aFilter,
+ const RMessagePtr2& aMessage)
+ {
+ TInt count = 0;
+ TSglQueIter<CSchedule> iter(iSchedules);
+ iter.SetToFirst();
+ CSchedule* schedule = NULL;
+ while ((schedule = iter++) != NULL)
+ {
+ if(aFilter == EAllSchedules || (schedule->Enabled() && schedule->HasTasks()))
+ {
+ //only add information for schedules that the client has permission to alter
+ if(schedule->IsAccessAllowed(aMessage))
+ {
+ if(aRefArray)
+ {
+ TSchedulerItemRef ref;
+ ref.iHandle = schedule->Id();
+ ref.iName = schedule->Name();
+ aRefArray->AppendL(ref);
+ }
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
+// If aRefArray is NULL then only count it returned.
+TInt CTaskScheduler::GetTaskRefsL(CArrayFixFlat<TSchedulerItemRef>* aRefArray,
+ TScheduleFilter aScheduleFilter,
+ TTaskFilter aTaskFilter,
+ CClientProxy* aClient,
+ const RMessagePtr2& aMessage)
+ {
+ TInt count = 0;
+ TSglQueIter<CSchedule> iter(iSchedules);
+ iter.SetToFirst();
+ CSchedule* schedule = NULL;
+ while ((schedule = iter++) != NULL)
+ {
+ if(aScheduleFilter == EAllSchedules || (schedule->Enabled() && schedule->HasTasks()))
+ {
+ //only add information for schedules that the client has permission to alter
+ if(schedule->IsAccessAllowed(aMessage))
+ {
+ TSglQueIter<TScheduledTask> taskIter(*(schedule->Tasks()));
+ taskIter.SetToFirst();
+ TScheduledTask* task;
+ while ((task=taskIter++)!=NULL)
+ {
+ if (aTaskFilter==EAllTasks||&task->Client() == aClient) // This pointer comparison is a bit rubbish. Change?
+ {
+ if(aRefArray)
+ {
+ TTaskInfo info = task->Info();
+ TSchedulerItemRef ref;
+ ref.iHandle = info.iTaskId;
+ ref.iName = info.iName;
+ aRefArray->AppendL(ref);
+ }
+ count++;
+ }
+ }
+ }
+ }
+ }
+ return count;
+ }
+
+
+//
+// Schedule Execution functions
+//
+
+// A schedule is ready to be run
+void CTaskScheduler::DueTaskNotifyL(TInt aScheduleHandle)
+ {
+ CSchedule* schedule = FindL(aScheduleHandle);
+ //NotifyTasks() also removes tasks from the schedule if there are no
+ //repeats left.
+ schedule->NotifyTasks();
+
+ if (!schedule->HasTasks())
+ {
+ // remove schedule.
+ TRAPD(ignore, DoRemoveL(schedule));
+ //??error only occurs in relation to persistence!! Do something.
+ UNUSED_VAR(ignore);
+ }
+ else
+ {
+ __ASSERT_ALWAYS(IsStartupStateNonCritical(), User::Invariant());
+ iScheduleCriteriaManager->ReplaceScheduleL(*schedule,EConditionAndTime,ETrue);
+ }
+
+ // Execute all clients. This method doesn't leave as all errors are either
+ // logged in the log engine or handled elsewhere.
+ ExecuteClients();
+ }
+
+// Go through all clients, executing their tasks
+void CTaskScheduler::ExecuteClients(TBool aUpdateClient)
+ {
+ if ((BUROperationInProgress() == EBUROperationNoActivity) || !aUpdateClient)
+ {
+ TDblQueIter<CClientProxy> clientIter(iClients);
+ clientIter.SetToFirst();
+ CClientProxy* client;
+ while( (client = clientIter++) != NULL)
+ {
+ // Does this client have anything ready to run?
+ if (client->IsReadyToExecute())
+ {
+ client->ExecuteTasks();
+ // Clears the 'IsReadyToExecute' flag...
+ client->RemoveDueTasks();
+ }
+ }
+ if (aUpdateClient)
+ {
+ // Update the store file now
+ UpdateClients();
+ }
+ }
+ else
+ {
+ // Sets the flag to trigger delayed store operation when BUR ends
+ iTaskExecutedDuringBUR = ETrue;
+ }
+ }
+
+// Go through all clients, update the store file with modified client info
+void CTaskScheduler::UpdateClients()
+ {
+ // iterate the client list to perform delayed update of the store file
+ TDblQueIter<CClientProxy> clientIter(iClients);
+ clientIter.SetToFirst();
+ CClientProxy* client;
+ while( (client = clientIter++) != NULL)
+ {
+ if (!client->Users())
+ {
+ // Remove from store
+ TRAPD(ignore, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationDelete, *client));
+ //?? if ignore is not KErrNone then there is a problem with the store
+ UNUSED_VAR(ignore);
+ // Remove client & delete it
+ client->Remove();
+ delete client;
+ }
+ else
+ {
+ // Update this clients data in the store...
+ TRAPD(ignore, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *client));
+
+ //?? if ignore is not KErrNone then there is a problem with the store
+ UNUSED_VAR(ignore);
+ }
+ }
+ }
+
+//
+// Environment change functions
+//
+
+TInt CTaskScheduler::EnvironmentChanged(TAny* aScheduler)
+ {
+ CTaskScheduler* self = reinterpret_cast<CTaskScheduler*>(aScheduler);
+ self->HandleEnvironmentChange();
+ return KErrNone;
+ }
+
+void CTaskScheduler::HandleEnvironmentChange()
+ {
+ // If staged startup still in critical region, can safely
+ // ignore system time change.
+ if (!IsStartupStateNonCritical())
+ {
+ return;
+ }
+
+ TInt changes=iNotifier->Change();
+ if (changes & EChangesSystemTime)
+ {
+#ifdef __SCHLOGGING__
+ {
+ TTime time;
+ time.HomeTime();
+ TDateTime due(time.DateTime());
+ LOGSTRING7("CTaskScheduler::HandleEnvironmentChangeL - system time is now: [%02d/%02d/%d] @ %02d:%02d:%02d", due.Day(), (TInt) due.Month() + 1, due.Year(), due.Hour(), due.Minute(), due.Second());
+ }
+#endif
+
+
+ // Cannot use AddSchedulesToTimerL() because this method
+ // uses the non-condition version of ReplaceScheduleL.
+ TSglQueIter<CSchedule> scheduleIter(iSchedules);
+ scheduleIter.SetToFirst();
+ CSchedule* schedule = NULL;
+ while ((schedule=scheduleIter++)!=NULL)
+ {
+ if(IsScheduleReadyForUpdate(*schedule))
+ {
+ TRAPD(err, iScheduleCriteriaManager->ReplaceScheduleL(*schedule, EOnlyTime));
+ UNUSED_VAR(err);
+ }
+ }
+ }
+ }
+
+void CTaskScheduler::AddSchedulesToTimerL()
+ {
+ if (!IsStartupStateNonCritical())
+ {
+ return; // not ready
+ }
+
+ TInt ret = KErrNone;
+
+ TSglQueIter<CSchedule> scheduleIter(iSchedules);
+ scheduleIter.SetToFirst();
+ CSchedule* schedule = NULL;
+ while ((schedule=scheduleIter++)!=NULL)
+ {
+ if(IsScheduleReadyForUpdate(*schedule))
+ {
+ TRAPD(err, iScheduleCriteriaManager->ReplaceScheduleL(*schedule));
+ if (err != KErrNone)
+ {
+ ret = err;
+ }
+ }
+ }
+ User::LeaveIfError(ret);
+ }
+
+void CTaskScheduler::CleanupScheduledTasksL()
+ {
+ RFs fs;
+ _LIT(KTempFilePath, "_:\\private\\10005399\\*.tmp");
+ TBuf<32> filePath(KTempFilePath);
+
+ filePath[0] = RFs::GetSystemDriveChar();
+
+ fs.Connect();
+ CleanupClosePushL(fs);
+
+ CFileMan* fileMan = CFileMan::NewL(fs);
+ CleanupStack::PushL(fileMan);
+
+ //Delete all temporary files in the private folder
+ fileMan->Delete(filePath,0);
+
+ //Pop and destroy fs and fileMan
+ //This will call fs.Close() so no need to call it explicitly
+ CleanupStack::PopAndDestroy(2);
+ }
+
+/**
+CSchStartupStateMgr calls this to notify startup state changes of
+interest.
+
+@internalComponent
+*/
+void CTaskScheduler::ProcessSSAEventL(TStartupStateIdentifier aKnownState)
+ {
+ LOGSTRING2("ProcessSSAEventL receive SS 0x%x", aKnownState);
+
+ if (! IsStartupStateNonCritical() &&
+ (aKnownState >= KSchFinalStartupState))
+ {
+ iStartupStatePassNonCritical = ETrue;
+ CleanupScheduledTasksL();
+ AddSchedulesToTimerL();
+ }
+ }
+
+/**
+Returns ETrue if Start-up State is NonCritical
+*/
+TBool CTaskScheduler::IsStartupStateNonCritical()
+ {
+ return iStartupStatePassNonCritical;
+ }
+
+/**
+Check schedule is valid
+*/
+TBool CTaskScheduler::IsScheduleReadyForUpdate(CSchedule& aSchedule)
+ {
+ if(aSchedule.IsUpdatable() && IsStartupStateNonCritical())
+ return ETrue;
+ else
+ return EFalse;
+ }
+
+/**
+babackup server calls this to notify backup operations. The attributes are read and translated to determine
+which operation is actually in progress.
+@internalComponent
+*/
+void CTaskScheduler::HandleBackupOperationEventL(const TBackupOperationAttributes& aBackupOperationAttributes)
+ {
+ TBUROperation type;
+
+ // determine the operation type (backup or restore)
+ switch(aBackupOperationAttributes.iFileFlag)
+ {
+ case MBackupObserver::EReleaseLockReadOnly:
+ type = EBUROperationBackup;
+ break;
+ case MBackupObserver::EReleaseLockNoAccess:
+ type = EBUROperationRestore;
+ break;
+ case MBackupObserver::ETakeLock:
+ // No information is passed from babackup server, so we need to depend on our own memory
+ type = iBUROperationInProgress;
+ break;
+ default:
+ type = EBUROperationNoActivity;
+ break;
+ }
+
+ // determine the operation status (e.g. starting, ending)
+ switch(aBackupOperationAttributes.iOperation)
+ {
+ case EStart:
+ BURBeginningL(type);
+ break;
+ case EEnd:
+ BURCompleteL(type, EBUROperationSuccess);
+ break;
+ case EAbort:
+ BURCompleteL(type, EBUROperationAbort);
+ break;
+ default:
+ break;
+ }
+ }
+
+
+/**
+This function is called to notify when a Backup or Restore operation is commencing.
+
+@internalComponent
+*/
+void CTaskScheduler::BURBeginningL(TBUROperation aOperationType)
+{
+ // This will stop the API calls that directly modify the store file
+ iBUROperationInProgress = aOperationType;
+
+ //cancel background compaction of store during backup/restore
+ iBackupManager->Cancel();
+}
+
+
+/**
+This function is called to notify when a Backup or Restore operation is finished.
+
+@internalComponent
+*/
+void CTaskScheduler::BURCompleteL(TBUROperation aOperationType, TBUROperationResult aBURResult)
+{
+ // If there is a successful restore, this means that we have a different store file then we were using
+ // so we have to internalize and use that file. In any other case, we can proceed with the delayed
+ // updates to the old file
+ if ((aOperationType == EBUROperationRestore)&&(aBURResult == EBUROperationSuccess))
+ {
+ LOGSTRING("CTaskScheduler::BURCompleteL - Restoring clients and schedules after successful restore");
+
+ //First check whether any task expires during the restore process now that this is completed
+ if (iTaskExecutedDuringBUR)
+ {
+ // performed the delayed task execution but with no externalizing as we dont want to modify
+ // the just restored file as after the delayed execution, all persistent schedule will be removed
+ ExecuteClients(EFalse);
+ iTaskExecutedDuringBUR=EFalse;
+ }
+
+ // Now remove existing persistent schedules, tasks and clients
+ TSglQueIter<CSchedule> scheduleIter(iSchedules);
+ scheduleIter.SetToFirst();
+ CSchedule* schedule;
+ while ((schedule = scheduleIter++)!=NULL)
+ {
+ if (schedule->Persists())
+ {
+ iSchedules.Remove(*schedule);
+ schedule->RemoveTasks(ETrue);
+ delete schedule;
+ }
+ }
+
+ CClientProxy* client;
+ TDblQueIter<CClientProxy> clientIter(iClients);
+
+ // remove clients which don't have any associated tasks left (tasks in persistent schedules are
+ // already removed, but the client might have transient schedules as well)
+ clientIter.SetToFirst();
+ while ((client = clientIter++) != NULL)
+ {
+ TDblQueIter<CScheduledTask> taskIter = client->TaskIterator();
+ taskIter.SetToFirst();
+
+ // remove client if no more tasks
+ if (taskIter++ == NULL)
+ {
+ client->Remove();
+ delete client; // removes associated tasks
+ }
+ else
+ {
+ //remove any persisted task and if the client only has persisted task, remove client as well
+ taskIter.SetToFirst();
+ CScheduledTask* task;
+ TInt taskCount=0;
+ TInt persistCount=0;
+ while ((task = taskIter++) != NULL)
+ {
+ taskCount++;
+ if (task->Persists())
+ {
+ persistCount++;
+ client->RemoveTask(task);
+ }
+ }
+ //if after removing the persist tasks, there are no more other tasks, we can remove the client too
+ if (taskCount==persistCount)
+ {
+ client->Remove();
+ delete client;
+ }
+ }
+ }
+
+ // now re-read the clients and schedules from the restored store file
+ TRAPD(err, iBackupManager->RestoreL(iClients, iSchedules,*iSchLogManager,ETrue));
+
+ if (err != KErrNone) // the file's corrupt or something...
+ {
+ LOGSTRING2("CTaskScheduler::BURCompleteL - had to create new store because of error: %d", err);
+ iBackupManager->CreateEmptyBackupL();
+ }
+
+
+ // Each client now contains a list of associated tasks. We need
+ // to now associate those tasks with specific schedules
+ clientIter.SetToFirst();
+ while ((client = clientIter++) != NULL)
+ {
+ // Fetch an iterator for each task owned by this client
+ CScheduledTask* task;
+ TDblQueIter<CScheduledTask> taskIterator = client->TaskIterator();
+ taskIterator.SetToFirst();
+
+ // Iterate through all the tasks owned by this client, trying to find
+ // the corresponding schedules.
+ while ((task = taskIterator++) != NULL)
+ {
+ TSglQueIter<CSchedule> persScheduleIter(iSchedules);
+ persScheduleIter.SetToFirst();
+ CSchedule* persSchedule;
+ while ((persSchedule = persScheduleIter++)!=NULL)
+ {
+ if ((persSchedule->Persists())&&(persSchedule->Id() == task->ScheduleId()))
+ {
+ TScheduledTask* taskRef = new(ELeave) TScheduledTask(*task,*client);
+ persSchedule->AddTask(*taskRef);
+ }
+ }
+ }
+ }
+
+ // Activate the scheduler with the new schedules
+ AddSchedulesToTimerL();
+ }
+ else
+ {
+ if (iTaskExecutedDuringBUR)
+ {
+ iBUROperationInProgress = EBUROperationNoActivity;
+ iTaskExecutedDuringBUR = EFalse;
+ // performed the delayed task execution
+ ExecuteClients();
+ }
+ }
+
+ // BUR operation is completed
+ iBUROperationInProgress = EBUROperationNoActivity;
+ iTaskExecutedDuringBUR = EFalse;
+}