os/ossrv/genericservices/taskscheduler/SCHSVR/SCHMAN.CPP
changeset 0 bde4ae8d615e
     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 +}