1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericservices/taskscheduler/SCHSVR/SCHMAN.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,912 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +// System includes
1.20 +#include <bacntf.h>
1.21 +
1.22 +// User includes
1.23 +#include "SCHMAN.H"
1.24 +#include "SchTimer.h"
1.25 +#include "SchLogger.h"
1.26 +#include "SCHEDULE.H"
1.27 +#include "SCHCLI.H"
1.28 +#include "SCHSTORE.H"
1.29 +#include <schtask.h>
1.30 +#include "SCHLOG.h"
1.31 +
1.32 +// Constants
1.33 +const TInt KMinScheduleId = 0;
1.34 +const TInt KMaxSchedules = 25000;
1.35 +
1.36 +//Command line argument
1.37 +_LIT(KCommandLine, "SYSSTARTSCHEXE");
1.38 +
1.39 +//SID of SysStart
1.40 +const TInt KSysStartSID = 0x10205C44;
1.41 +
1.42 +
1.43 +#define UNUSED_VAR(a) a = a
1.44 +
1.45 +//
1.46 +// Construction/Destruction functions
1.47 +//
1.48 +
1.49 +CTaskScheduler::CTaskScheduler()
1.50 +: iSchedules(CSchedule::Offset()),
1.51 + iClients(CClientProxy::Offset()),
1.52 + iStartupStatePassNonCritical(EFalse)
1.53 + {
1.54 + }
1.55 +
1.56 +CTaskScheduler::~CTaskScheduler()
1.57 + {
1.58 + if (iBackupNotification)
1.59 + {
1.60 + iBackupNotification->DeRegisterBackupOperationObserver(*this);
1.61 + }
1.62 + delete iBackupNotification;
1.63 + delete iBackupManager;
1.64 + delete iNotifier;
1.65 + delete iScheduleCriteriaManager;
1.66 + delete iSchLogManager;
1.67 +
1.68 + //remove clients and schedules as well!!
1.69 + TDblQueIter<CClientProxy> clientIter(iClients);
1.70 +
1.71 + clientIter.SetToFirst();
1.72 + CClientProxy* client=NULL;
1.73 + while ((client=clientIter++)!=NULL)
1.74 + {
1.75 + client->Remove();
1.76 + delete client;
1.77 + }
1.78 +
1.79 + TSglQueIter<CSchedule> schedIter(iSchedules);
1.80 +
1.81 + schedIter.SetToFirst();
1.82 + CSchedule* schedule=NULL;
1.83 + while ((schedule=schedIter++)!=NULL)
1.84 + {
1.85 + iSchedules.Remove(*schedule);
1.86 + delete schedule;
1.87 + }
1.88 + }
1.89 +
1.90 +void CTaskScheduler::ConstructL()
1.91 + {
1.92 + LOGSTRING("CTaskScheduler::ConstructL - Creating new schedule server log entry");
1.93 +
1.94 + User::LeaveIfError(iFsSession.Connect());
1.95 + iBackupManager = new(ELeave) CSchBackupManager(iFsSession);
1.96 + iBackupManager->ConstructL();
1.97 +
1.98 + iNotifier = CEnvironmentChangeNotifier::NewL(CActive::EPriorityHigh, TCallBack(EnvironmentChanged, this));
1.99 + iNotifier->Start();
1.100 +
1.101 + iScheduleCriteriaManager = CScheduleCriteriaManager::NewL(*this);
1.102 +
1.103 + iSchLogManager = CSchLogManager::NewL(iFsSession);
1.104 +
1.105 + LOGSTRING("CTaskScheduler::ConstructL - Restoring clients and schedules");
1.106 + TRAPD(err, iBackupManager->RestoreL(iClients, iSchedules,*iSchLogManager));
1.107 + if (err != KErrNone) // the file's corrupt or something...
1.108 + {
1.109 + LOGSTRING2("CTaskScheduler::ConstructL - had to create new store because of error: %d", err);
1.110 + iBackupManager->CreateEmptyBackupL();
1.111 + }
1.112 +
1.113 + //checking the SID of the process which started the Task scheduler
1.114 + if (User::CreatorSecureId() == KSysStartSID)
1.115 + {
1.116 + TInt argLen = User::CommandLineLength();
1.117 + if (argLen)
1.118 + {
1.119 + HBufC* arg = HBufC::NewLC(argLen);
1.120 + TPtr argPtr = arg->Des();
1.121 + User::CommandLine(argPtr);
1.122 + argPtr.UpperCase();
1.123 +
1.124 + //Checking Comman dLine arg passed to it is same as in SSCForStartupMode0.rss
1.125 + //and checking for persisted schedules
1.126 + if((argPtr.Compare(KCommandLine) == 0) && iSchedules.IsEmpty())
1.127 + {
1.128 + //if no schedule leave
1.129 + User::Leave(KErrNone);
1.130 + }
1.131 + CleanupStack::PopAndDestroy(arg);
1.132 + }
1.133 + }
1.134 +
1.135 + // Each client now contains a list of associated tasks. We need
1.136 + // to now associate those tasks with specific schedules
1.137 + CClientProxy* client;
1.138 + TDblQueIter<CClientProxy> clientIter(iClients);
1.139 + clientIter.SetToFirst();
1.140 + while ((client = clientIter++) != NULL)
1.141 + {
1.142 + // Fetch an iterator for each task owned by this client
1.143 + CScheduledTask* task;
1.144 + TDblQueIter<CScheduledTask> taskIterator = client->TaskIterator();
1.145 + taskIterator.SetToFirst();
1.146 +
1.147 + // Iterate through all the tasks owned by this client, trying to find
1.148 + // the corresponding schedules.
1.149 + while ((task = taskIterator++) != NULL)
1.150 + {
1.151 + CSchedule* schedule = NULL;
1.152 + schedule = Find(task->ScheduleId());
1.153 + if (schedule)
1.154 + {
1.155 + TScheduledTask* taskRef = new(ELeave) TScheduledTask(*task,*client);
1.156 + schedule->AddTask(*taskRef);
1.157 + }
1.158 + }
1.159 + }
1.160 + iBackupNotification = CBaBackupSessionWrapper::NewL();
1.161 + iBackupNotification->RegisterBackupOperationObserverL(*this);
1.162 + }
1.163 +
1.164 +CTaskScheduler* CTaskScheduler::NewL()
1.165 + {
1.166 + CTaskScheduler* self = CTaskScheduler::NewLC();
1.167 + CleanupStack::Pop();
1.168 + return self;
1.169 + }
1.170 +
1.171 +CTaskScheduler* CTaskScheduler::NewLC()
1.172 + {
1.173 + CTaskScheduler* self = new(ELeave) CTaskScheduler();
1.174 + CleanupStack::PushL(self);
1.175 + self->ConstructL();
1.176 + return self;
1.177 + }
1.178 +
1.179 +//
1.180 +// Client, Schedule and Task functions
1.181 +//
1.182 +
1.183 +CClientProxy* CTaskScheduler::AddClientL(const TDesC& aFilename, TInt aPriority)
1.184 + {
1.185 + //check we don't already have a client that will do...
1.186 + TDblQueIter<CClientProxy> clientIter(iClients);
1.187 + clientIter.SetToFirst();
1.188 + CClientProxy* client=NULL;
1.189 + while ((client=clientIter++)!=NULL)
1.190 + {
1.191 + if (client->IsEqual(aFilename, aPriority))
1.192 + return client;
1.193 + }
1.194 + client = CClientProxy::NewL(iFsSession, aFilename, aPriority,*iSchLogManager);
1.195 + iClients.Add(*client);
1.196 + return client;
1.197 + }
1.198 +
1.199 +void CTaskScheduler::AddScheduleL(CSchedule& aSchedule)
1.200 + {
1.201 + LOGSTRING3("CTaskScheduler::AddScheduleL - schedule: %S, %d", &aSchedule.Name(), aSchedule.Id());
1.202 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationAdd, aSchedule);
1.203 + iSchedules.AddLast(aSchedule);
1.204 + LOGSTRING("CTaskScheduler::AddScheduleL - schedule added");
1.205 + }
1.206 +
1.207 +void CTaskScheduler::EditScheduleL(TInt aScheduleHandle, CArrayFixFlat<TScheduleEntryInfo2>& aEntryList)
1.208 + {
1.209 + CSchedule* schedule = FindL(aScheduleHandle);
1.210 +
1.211 + // remove schedule from condition manager before replacing entries to ensure
1.212 + // its deleted properly.
1.213 + iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
1.214 + schedule->ReplaceEntriesL(aEntryList);
1.215 +
1.216 + TRAPD(err, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule));
1.217 + if(err)
1.218 + {
1.219 + schedule->RemoveEntries();
1.220 + User::Leave(err);
1.221 + }
1.222 + // recalculate due time only if schedule is enabled and has tasks to run
1.223 + if (IsScheduleReadyForUpdate(*schedule))
1.224 + {
1.225 + iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
1.226 + }
1.227 + }
1.228 +
1.229 +void CTaskScheduler::DoEditScheduleL(CSchedule& aSchedule,
1.230 + CArrayFixFlat<TTaskSchedulerCondition>& aConditionList,
1.231 + const TTsTime& aDefaultTime)
1.232 + {
1.233 + aSchedule.ReplaceConditionsL(aConditionList);
1.234 +
1.235 + //Default Time is represented by a single entry class
1.236 + CArrayFixFlat<TScheduleEntryInfo2>* entries
1.237 + = new(ELeave) CArrayFixFlat<TScheduleEntryInfo2>(1);
1.238 + CleanupStack::PushL(entries);
1.239 + TScheduleEntryInfo2 info;
1.240 + info.SetStartTime(aDefaultTime);
1.241 + info.SetInterval(1);
1.242 + info.SetIntervalType(EDaily);
1.243 + //validityperiod of 24 hours will ensure task is always run
1.244 + info.SetValidityPeriod(60*24);
1.245 + entries->AppendL(info);
1.246 + aSchedule.ReplaceEntriesL(*entries);
1.247 + CleanupStack::Pop(entries);
1.248 +
1.249 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, aSchedule);
1.250 + }
1.251 +
1.252 +void CTaskScheduler::EditScheduleL(TInt aScheduleHandle,
1.253 + CArrayFixFlat<TTaskSchedulerCondition>& aConditionList,
1.254 + const TTsTime& aDefaultTime)
1.255 + {
1.256 + CSchedule* schedule = FindL(aScheduleHandle);
1.257 +
1.258 + // remove schedule from condition manager before replacing entries to ensure
1.259 + // its deleted properly.
1.260 + iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
1.261 +
1.262 + TRAPD(err, DoEditScheduleL(*schedule, aConditionList, aDefaultTime));
1.263 + if(err)
1.264 + {
1.265 + schedule->RemoveEntries();
1.266 + schedule->RemoveConditions();
1.267 + User::Leave(err);
1.268 + }
1.269 +
1.270 + // recalculate due time only if schedule is enabled and has tasks to run
1.271 + if (IsScheduleReadyForUpdate(*schedule))
1.272 + {
1.273 + iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
1.274 + }
1.275 + }
1.276 +
1.277 +void CTaskScheduler::RemoveScheduleL(TInt aHandle)
1.278 + {
1.279 + CSchedule* schedule = FindL(aHandle);
1.280 + LOGSTRING3("CTaskScheduler::RemoveScheduleL - schedule: %S, %d", &schedule->Name(), schedule->Id());
1.281 + if (!schedule->HasTasks())
1.282 + {
1.283 + LOGSTRING("CTaskScheduler::RemoveScheduleL - schedule doesn't have any tasks, removing");
1.284 + //remove schedule from timer
1.285 + iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
1.286 + DoRemoveL(schedule);
1.287 + }
1.288 + else
1.289 + {
1.290 + // Can't delete a schedule which has tasks
1.291 + LOGSTRING("CTaskScheduler::RemoveScheduleL - schedule has tasks, can't delete");
1.292 + User::Leave(KErrArgument);
1.293 + }
1.294 + }
1.295 +
1.296 +void CTaskScheduler::DisableScheduleL(TInt aHandle)
1.297 + {
1.298 + CSchedule* schedule = FindL(aHandle);
1.299 + schedule->SetEnabled(EFalse);
1.300 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule);
1.301 + //remove schedule from timer as its disabled
1.302 + iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
1.303 + }
1.304 +
1.305 +void CTaskScheduler::EnableScheduleL(TInt aHandle)
1.306 + {
1.307 + CSchedule* schedule = FindL(aHandle);
1.308 + schedule->SetEnabled(ETrue);
1.309 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule);
1.310 +
1.311 + // recalculate due time only if schedule has tasks to run
1.312 + if ( IsScheduleReadyForUpdate(*schedule))
1.313 + {
1.314 + iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
1.315 + }
1.316 + }
1.317 +
1.318 +void CTaskScheduler::ScheduleTaskL(CSchedule& aSchedule, CClientProxy& aClient)
1.319 + {
1.320 + // Backup the task
1.321 + if (aSchedule.Persists())
1.322 + {
1.323 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, aClient);
1.324 + }
1.325 + // if schedule is enabled then add schedule to timer.
1.326 + if (aSchedule.Enabled() && IsStartupStateNonCritical())
1.327 + {
1.328 + iScheduleCriteriaManager->ReplaceScheduleL(aSchedule);
1.329 + }
1.330 + }
1.331 +
1.332 +void CTaskScheduler::DeleteTaskL(TInt aScheduleHandle, TInt aTaskHandle)
1.333 + {
1.334 + CSchedule* schedule = FindL(aScheduleHandle);
1.335 +
1.336 + TScheduledTask* task = schedule->Task(aTaskHandle);
1.337 + if (!task)
1.338 + {
1.339 + LOGSTRING("CTaskScheduler::DeleteTaskL - task wasn't found");
1.340 + User::Leave(KErrNotFound);
1.341 + }
1.342 +
1.343 + const CClientProxy& clientForTask = task->Client();
1.344 +
1.345 + // This deletes the task and removes the CScheduledTask
1.346 + // from the CClientProxy's queue of tasks
1.347 + task->RemoveInfo();
1.348 +
1.349 + // This deletes the TScheduledTask defined above and removes it
1.350 + // from CSchedule's queue of TScheduledTask's.
1.351 + schedule->RemoveTask(task);
1.352 + if (!schedule->HasTasks()) //i.e. it was the last task
1.353 + {
1.354 + LOGSTRING("CTaskScheduler::DeleteTaskL - schedule doesn't have any more tasks left");
1.355 + //remove scheule from timer as there are no more tasks
1.356 + iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
1.357 + // If the schedule isn't persistent then we delete it (transient schedules only
1.358 + // have one task).
1.359 + if (!schedule->Persists())
1.360 + DoRemoveL(schedule);
1.361 + else
1.362 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, clientForTask);
1.363 + }
1.364 + else
1.365 + {
1.366 + // Backup the changes to the tasks. Although we are deleting a task, we are not actually
1.367 + // deleting the client, so this is actually an edit operation.
1.368 + if (schedule->Persists())
1.369 + iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, clientForTask);
1.370 + }
1.371 + }
1.372 +
1.373 +//
1.374 +// Utility Functions
1.375 +//
1.376 +
1.377 +TInt CTaskScheduler::GenerateId()
1.378 + {
1.379 + TInt id = KMinScheduleId;
1.380 + CSchedule* schedule = Find(id);
1.381 + while (schedule!=NULL)
1.382 + {
1.383 + id+=KScheduleIdDifferential;//=10 000
1.384 + if ((id/KScheduleIdDifferential) > KMaxSchedules)
1.385 + return KErrOverflow;
1.386 + schedule = Find(id);
1.387 + }
1.388 + return id;
1.389 + }
1.390 +
1.391 +void CTaskScheduler::DoRemoveL(CSchedule* aSchedule)
1.392 + {
1.393 + TRAPD(err, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationDelete, *aSchedule));
1.394 + if (err < KErrNone && err != KErrNotFound)
1.395 + User::Leave(err);
1.396 + iSchedules.Remove(*aSchedule);
1.397 + delete aSchedule;
1.398 + aSchedule = NULL;
1.399 + }
1.400 +
1.401 +CSchedule* CTaskScheduler::FindL(TInt aHandle)
1.402 + {
1.403 + CSchedule* schedule = Find(aHandle);
1.404 + if (!schedule)
1.405 + User::Leave(KErrNotFound);
1.406 + return schedule;
1.407 + }
1.408 +
1.409 +CSchedule* CTaskScheduler::Find(TInt aHandle)
1.410 + {
1.411 + TSglQueIter<CSchedule> scheduleIter(iSchedules);
1.412 + scheduleIter.SetToFirst();
1.413 + CSchedule* schedule;
1.414 + while ((schedule = scheduleIter++)!=NULL)
1.415 + {
1.416 + if (schedule->Id() == aHandle)
1.417 + return schedule;
1.418 + }
1.419 + return NULL;
1.420 + }
1.421 +
1.422 +// If aRefArray is NULL then only count it returned.
1.423 +TInt CTaskScheduler::GetScheduleRefsL(CArrayFixFlat<TSchedulerItemRef>* aRefArray,
1.424 + TScheduleFilter aFilter,
1.425 + const RMessagePtr2& aMessage)
1.426 + {
1.427 + TInt count = 0;
1.428 + TSglQueIter<CSchedule> iter(iSchedules);
1.429 + iter.SetToFirst();
1.430 + CSchedule* schedule = NULL;
1.431 + while ((schedule = iter++) != NULL)
1.432 + {
1.433 + if(aFilter == EAllSchedules || (schedule->Enabled() && schedule->HasTasks()))
1.434 + {
1.435 + //only add information for schedules that the client has permission to alter
1.436 + if(schedule->IsAccessAllowed(aMessage))
1.437 + {
1.438 + if(aRefArray)
1.439 + {
1.440 + TSchedulerItemRef ref;
1.441 + ref.iHandle = schedule->Id();
1.442 + ref.iName = schedule->Name();
1.443 + aRefArray->AppendL(ref);
1.444 + }
1.445 + count++;
1.446 + }
1.447 + }
1.448 + }
1.449 + return count;
1.450 + }
1.451 +
1.452 +// If aRefArray is NULL then only count it returned.
1.453 +TInt CTaskScheduler::GetTaskRefsL(CArrayFixFlat<TSchedulerItemRef>* aRefArray,
1.454 + TScheduleFilter aScheduleFilter,
1.455 + TTaskFilter aTaskFilter,
1.456 + CClientProxy* aClient,
1.457 + const RMessagePtr2& aMessage)
1.458 + {
1.459 + TInt count = 0;
1.460 + TSglQueIter<CSchedule> iter(iSchedules);
1.461 + iter.SetToFirst();
1.462 + CSchedule* schedule = NULL;
1.463 + while ((schedule = iter++) != NULL)
1.464 + {
1.465 + if(aScheduleFilter == EAllSchedules || (schedule->Enabled() && schedule->HasTasks()))
1.466 + {
1.467 + //only add information for schedules that the client has permission to alter
1.468 + if(schedule->IsAccessAllowed(aMessage))
1.469 + {
1.470 + TSglQueIter<TScheduledTask> taskIter(*(schedule->Tasks()));
1.471 + taskIter.SetToFirst();
1.472 + TScheduledTask* task;
1.473 + while ((task=taskIter++)!=NULL)
1.474 + {
1.475 + if (aTaskFilter==EAllTasks||&task->Client() == aClient) // This pointer comparison is a bit rubbish. Change?
1.476 + {
1.477 + if(aRefArray)
1.478 + {
1.479 + TTaskInfo info = task->Info();
1.480 + TSchedulerItemRef ref;
1.481 + ref.iHandle = info.iTaskId;
1.482 + ref.iName = info.iName;
1.483 + aRefArray->AppendL(ref);
1.484 + }
1.485 + count++;
1.486 + }
1.487 + }
1.488 + }
1.489 + }
1.490 + }
1.491 + return count;
1.492 + }
1.493 +
1.494 +
1.495 +//
1.496 +// Schedule Execution functions
1.497 +//
1.498 +
1.499 +// A schedule is ready to be run
1.500 +void CTaskScheduler::DueTaskNotifyL(TInt aScheduleHandle)
1.501 + {
1.502 + CSchedule* schedule = FindL(aScheduleHandle);
1.503 + //NotifyTasks() also removes tasks from the schedule if there are no
1.504 + //repeats left.
1.505 + schedule->NotifyTasks();
1.506 +
1.507 + if (!schedule->HasTasks())
1.508 + {
1.509 + // remove schedule.
1.510 + TRAPD(ignore, DoRemoveL(schedule));
1.511 + //??error only occurs in relation to persistence!! Do something.
1.512 + UNUSED_VAR(ignore);
1.513 + }
1.514 + else
1.515 + {
1.516 + __ASSERT_ALWAYS(IsStartupStateNonCritical(), User::Invariant());
1.517 + iScheduleCriteriaManager->ReplaceScheduleL(*schedule,EConditionAndTime,ETrue);
1.518 + }
1.519 +
1.520 + // Execute all clients. This method doesn't leave as all errors are either
1.521 + // logged in the log engine or handled elsewhere.
1.522 + ExecuteClients();
1.523 + }
1.524 +
1.525 +// Go through all clients, executing their tasks
1.526 +void CTaskScheduler::ExecuteClients(TBool aUpdateClient)
1.527 + {
1.528 + if ((BUROperationInProgress() == EBUROperationNoActivity) || !aUpdateClient)
1.529 + {
1.530 + TDblQueIter<CClientProxy> clientIter(iClients);
1.531 + clientIter.SetToFirst();
1.532 + CClientProxy* client;
1.533 + while( (client = clientIter++) != NULL)
1.534 + {
1.535 + // Does this client have anything ready to run?
1.536 + if (client->IsReadyToExecute())
1.537 + {
1.538 + client->ExecuteTasks();
1.539 + // Clears the 'IsReadyToExecute' flag...
1.540 + client->RemoveDueTasks();
1.541 + }
1.542 + }
1.543 + if (aUpdateClient)
1.544 + {
1.545 + // Update the store file now
1.546 + UpdateClients();
1.547 + }
1.548 + }
1.549 + else
1.550 + {
1.551 + // Sets the flag to trigger delayed store operation when BUR ends
1.552 + iTaskExecutedDuringBUR = ETrue;
1.553 + }
1.554 + }
1.555 +
1.556 +// Go through all clients, update the store file with modified client info
1.557 +void CTaskScheduler::UpdateClients()
1.558 + {
1.559 + // iterate the client list to perform delayed update of the store file
1.560 + TDblQueIter<CClientProxy> clientIter(iClients);
1.561 + clientIter.SetToFirst();
1.562 + CClientProxy* client;
1.563 + while( (client = clientIter++) != NULL)
1.564 + {
1.565 + if (!client->Users())
1.566 + {
1.567 + // Remove from store
1.568 + TRAPD(ignore, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationDelete, *client));
1.569 + //?? if ignore is not KErrNone then there is a problem with the store
1.570 + UNUSED_VAR(ignore);
1.571 + // Remove client & delete it
1.572 + client->Remove();
1.573 + delete client;
1.574 + }
1.575 + else
1.576 + {
1.577 + // Update this clients data in the store...
1.578 + TRAPD(ignore, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *client));
1.579 +
1.580 + //?? if ignore is not KErrNone then there is a problem with the store
1.581 + UNUSED_VAR(ignore);
1.582 + }
1.583 + }
1.584 + }
1.585 +
1.586 +//
1.587 +// Environment change functions
1.588 +//
1.589 +
1.590 +TInt CTaskScheduler::EnvironmentChanged(TAny* aScheduler)
1.591 + {
1.592 + CTaskScheduler* self = reinterpret_cast<CTaskScheduler*>(aScheduler);
1.593 + self->HandleEnvironmentChange();
1.594 + return KErrNone;
1.595 + }
1.596 +
1.597 +void CTaskScheduler::HandleEnvironmentChange()
1.598 + {
1.599 + // If staged startup still in critical region, can safely
1.600 + // ignore system time change.
1.601 + if (!IsStartupStateNonCritical())
1.602 + {
1.603 + return;
1.604 + }
1.605 +
1.606 + TInt changes=iNotifier->Change();
1.607 + if (changes & EChangesSystemTime)
1.608 + {
1.609 +#ifdef __SCHLOGGING__
1.610 + {
1.611 + TTime time;
1.612 + time.HomeTime();
1.613 + TDateTime due(time.DateTime());
1.614 + 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());
1.615 + }
1.616 +#endif
1.617 +
1.618 +
1.619 + // Cannot use AddSchedulesToTimerL() because this method
1.620 + // uses the non-condition version of ReplaceScheduleL.
1.621 + TSglQueIter<CSchedule> scheduleIter(iSchedules);
1.622 + scheduleIter.SetToFirst();
1.623 + CSchedule* schedule = NULL;
1.624 + while ((schedule=scheduleIter++)!=NULL)
1.625 + {
1.626 + if(IsScheduleReadyForUpdate(*schedule))
1.627 + {
1.628 + TRAPD(err, iScheduleCriteriaManager->ReplaceScheduleL(*schedule, EOnlyTime));
1.629 + UNUSED_VAR(err);
1.630 + }
1.631 + }
1.632 + }
1.633 + }
1.634 +
1.635 +void CTaskScheduler::AddSchedulesToTimerL()
1.636 + {
1.637 + if (!IsStartupStateNonCritical())
1.638 + {
1.639 + return; // not ready
1.640 + }
1.641 +
1.642 + TInt ret = KErrNone;
1.643 +
1.644 + TSglQueIter<CSchedule> scheduleIter(iSchedules);
1.645 + scheduleIter.SetToFirst();
1.646 + CSchedule* schedule = NULL;
1.647 + while ((schedule=scheduleIter++)!=NULL)
1.648 + {
1.649 + if(IsScheduleReadyForUpdate(*schedule))
1.650 + {
1.651 + TRAPD(err, iScheduleCriteriaManager->ReplaceScheduleL(*schedule));
1.652 + if (err != KErrNone)
1.653 + {
1.654 + ret = err;
1.655 + }
1.656 + }
1.657 + }
1.658 + User::LeaveIfError(ret);
1.659 + }
1.660 +
1.661 +void CTaskScheduler::CleanupScheduledTasksL()
1.662 + {
1.663 + RFs fs;
1.664 + _LIT(KTempFilePath, "_:\\private\\10005399\\*.tmp");
1.665 + TBuf<32> filePath(KTempFilePath);
1.666 +
1.667 + filePath[0] = RFs::GetSystemDriveChar();
1.668 +
1.669 + fs.Connect();
1.670 + CleanupClosePushL(fs);
1.671 +
1.672 + CFileMan* fileMan = CFileMan::NewL(fs);
1.673 + CleanupStack::PushL(fileMan);
1.674 +
1.675 + //Delete all temporary files in the private folder
1.676 + fileMan->Delete(filePath,0);
1.677 +
1.678 + //Pop and destroy fs and fileMan
1.679 + //This will call fs.Close() so no need to call it explicitly
1.680 + CleanupStack::PopAndDestroy(2);
1.681 + }
1.682 +
1.683 +/**
1.684 +CSchStartupStateMgr calls this to notify startup state changes of
1.685 +interest.
1.686 +
1.687 +@internalComponent
1.688 +*/
1.689 +void CTaskScheduler::ProcessSSAEventL(TStartupStateIdentifier aKnownState)
1.690 + {
1.691 + LOGSTRING2("ProcessSSAEventL receive SS 0x%x", aKnownState);
1.692 +
1.693 + if (! IsStartupStateNonCritical() &&
1.694 + (aKnownState >= KSchFinalStartupState))
1.695 + {
1.696 + iStartupStatePassNonCritical = ETrue;
1.697 + CleanupScheduledTasksL();
1.698 + AddSchedulesToTimerL();
1.699 + }
1.700 + }
1.701 +
1.702 +/**
1.703 +Returns ETrue if Start-up State is NonCritical
1.704 +*/
1.705 +TBool CTaskScheduler::IsStartupStateNonCritical()
1.706 + {
1.707 + return iStartupStatePassNonCritical;
1.708 + }
1.709 +
1.710 +/**
1.711 +Check schedule is valid
1.712 +*/
1.713 +TBool CTaskScheduler::IsScheduleReadyForUpdate(CSchedule& aSchedule)
1.714 + {
1.715 + if(aSchedule.IsUpdatable() && IsStartupStateNonCritical())
1.716 + return ETrue;
1.717 + else
1.718 + return EFalse;
1.719 + }
1.720 +
1.721 +/**
1.722 +babackup server calls this to notify backup operations. The attributes are read and translated to determine
1.723 +which operation is actually in progress.
1.724 +@internalComponent
1.725 +*/
1.726 +void CTaskScheduler::HandleBackupOperationEventL(const TBackupOperationAttributes& aBackupOperationAttributes)
1.727 + {
1.728 + TBUROperation type;
1.729 +
1.730 + // determine the operation type (backup or restore)
1.731 + switch(aBackupOperationAttributes.iFileFlag)
1.732 + {
1.733 + case MBackupObserver::EReleaseLockReadOnly:
1.734 + type = EBUROperationBackup;
1.735 + break;
1.736 + case MBackupObserver::EReleaseLockNoAccess:
1.737 + type = EBUROperationRestore;
1.738 + break;
1.739 + case MBackupObserver::ETakeLock:
1.740 + // No information is passed from babackup server, so we need to depend on our own memory
1.741 + type = iBUROperationInProgress;
1.742 + break;
1.743 + default:
1.744 + type = EBUROperationNoActivity;
1.745 + break;
1.746 + }
1.747 +
1.748 + // determine the operation status (e.g. starting, ending)
1.749 + switch(aBackupOperationAttributes.iOperation)
1.750 + {
1.751 + case EStart:
1.752 + BURBeginningL(type);
1.753 + break;
1.754 + case EEnd:
1.755 + BURCompleteL(type, EBUROperationSuccess);
1.756 + break;
1.757 + case EAbort:
1.758 + BURCompleteL(type, EBUROperationAbort);
1.759 + break;
1.760 + default:
1.761 + break;
1.762 + }
1.763 + }
1.764 +
1.765 +
1.766 +/**
1.767 +This function is called to notify when a Backup or Restore operation is commencing.
1.768 +
1.769 +@internalComponent
1.770 +*/
1.771 +void CTaskScheduler::BURBeginningL(TBUROperation aOperationType)
1.772 +{
1.773 + // This will stop the API calls that directly modify the store file
1.774 + iBUROperationInProgress = aOperationType;
1.775 +
1.776 + //cancel background compaction of store during backup/restore
1.777 + iBackupManager->Cancel();
1.778 +}
1.779 +
1.780 +
1.781 +/**
1.782 +This function is called to notify when a Backup or Restore operation is finished.
1.783 +
1.784 +@internalComponent
1.785 +*/
1.786 +void CTaskScheduler::BURCompleteL(TBUROperation aOperationType, TBUROperationResult aBURResult)
1.787 +{
1.788 + // If there is a successful restore, this means that we have a different store file then we were using
1.789 + // so we have to internalize and use that file. In any other case, we can proceed with the delayed
1.790 + // updates to the old file
1.791 + if ((aOperationType == EBUROperationRestore)&&(aBURResult == EBUROperationSuccess))
1.792 + {
1.793 + LOGSTRING("CTaskScheduler::BURCompleteL - Restoring clients and schedules after successful restore");
1.794 +
1.795 + //First check whether any task expires during the restore process now that this is completed
1.796 + if (iTaskExecutedDuringBUR)
1.797 + {
1.798 + // performed the delayed task execution but with no externalizing as we dont want to modify
1.799 + // the just restored file as after the delayed execution, all persistent schedule will be removed
1.800 + ExecuteClients(EFalse);
1.801 + iTaskExecutedDuringBUR=EFalse;
1.802 + }
1.803 +
1.804 + // Now remove existing persistent schedules, tasks and clients
1.805 + TSglQueIter<CSchedule> scheduleIter(iSchedules);
1.806 + scheduleIter.SetToFirst();
1.807 + CSchedule* schedule;
1.808 + while ((schedule = scheduleIter++)!=NULL)
1.809 + {
1.810 + if (schedule->Persists())
1.811 + {
1.812 + iSchedules.Remove(*schedule);
1.813 + schedule->RemoveTasks(ETrue);
1.814 + delete schedule;
1.815 + }
1.816 + }
1.817 +
1.818 + CClientProxy* client;
1.819 + TDblQueIter<CClientProxy> clientIter(iClients);
1.820 +
1.821 + // remove clients which don't have any associated tasks left (tasks in persistent schedules are
1.822 + // already removed, but the client might have transient schedules as well)
1.823 + clientIter.SetToFirst();
1.824 + while ((client = clientIter++) != NULL)
1.825 + {
1.826 + TDblQueIter<CScheduledTask> taskIter = client->TaskIterator();
1.827 + taskIter.SetToFirst();
1.828 +
1.829 + // remove client if no more tasks
1.830 + if (taskIter++ == NULL)
1.831 + {
1.832 + client->Remove();
1.833 + delete client; // removes associated tasks
1.834 + }
1.835 + else
1.836 + {
1.837 + //remove any persisted task and if the client only has persisted task, remove client as well
1.838 + taskIter.SetToFirst();
1.839 + CScheduledTask* task;
1.840 + TInt taskCount=0;
1.841 + TInt persistCount=0;
1.842 + while ((task = taskIter++) != NULL)
1.843 + {
1.844 + taskCount++;
1.845 + if (task->Persists())
1.846 + {
1.847 + persistCount++;
1.848 + client->RemoveTask(task);
1.849 + }
1.850 + }
1.851 + //if after removing the persist tasks, there are no more other tasks, we can remove the client too
1.852 + if (taskCount==persistCount)
1.853 + {
1.854 + client->Remove();
1.855 + delete client;
1.856 + }
1.857 + }
1.858 + }
1.859 +
1.860 + // now re-read the clients and schedules from the restored store file
1.861 + TRAPD(err, iBackupManager->RestoreL(iClients, iSchedules,*iSchLogManager,ETrue));
1.862 +
1.863 + if (err != KErrNone) // the file's corrupt or something...
1.864 + {
1.865 + LOGSTRING2("CTaskScheduler::BURCompleteL - had to create new store because of error: %d", err);
1.866 + iBackupManager->CreateEmptyBackupL();
1.867 + }
1.868 +
1.869 +
1.870 + // Each client now contains a list of associated tasks. We need
1.871 + // to now associate those tasks with specific schedules
1.872 + clientIter.SetToFirst();
1.873 + while ((client = clientIter++) != NULL)
1.874 + {
1.875 + // Fetch an iterator for each task owned by this client
1.876 + CScheduledTask* task;
1.877 + TDblQueIter<CScheduledTask> taskIterator = client->TaskIterator();
1.878 + taskIterator.SetToFirst();
1.879 +
1.880 + // Iterate through all the tasks owned by this client, trying to find
1.881 + // the corresponding schedules.
1.882 + while ((task = taskIterator++) != NULL)
1.883 + {
1.884 + TSglQueIter<CSchedule> persScheduleIter(iSchedules);
1.885 + persScheduleIter.SetToFirst();
1.886 + CSchedule* persSchedule;
1.887 + while ((persSchedule = persScheduleIter++)!=NULL)
1.888 + {
1.889 + if ((persSchedule->Persists())&&(persSchedule->Id() == task->ScheduleId()))
1.890 + {
1.891 + TScheduledTask* taskRef = new(ELeave) TScheduledTask(*task,*client);
1.892 + persSchedule->AddTask(*taskRef);
1.893 + }
1.894 + }
1.895 + }
1.896 + }
1.897 +
1.898 + // Activate the scheduler with the new schedules
1.899 + AddSchedulesToTimerL();
1.900 + }
1.901 + else
1.902 + {
1.903 + if (iTaskExecutedDuringBUR)
1.904 + {
1.905 + iBUROperationInProgress = EBUROperationNoActivity;
1.906 + iTaskExecutedDuringBUR = EFalse;
1.907 + // performed the delayed task execution
1.908 + ExecuteClients();
1.909 + }
1.910 + }
1.911 +
1.912 + // BUR operation is completed
1.913 + iBUROperationInProgress = EBUROperationNoActivity;
1.914 + iTaskExecutedDuringBUR = EFalse;
1.915 +}