genericservices/taskscheduler/SCHSVR/SCHMAN.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // System includes
       
    17 #include <bacntf.h>
       
    18 
       
    19 // User includes
       
    20 #include "SCHMAN.H"
       
    21 #include "SchTimer.h"
       
    22 #include "SchLogger.h"
       
    23 #include "SCHEDULE.H"
       
    24 #include "SCHCLI.H"
       
    25 #include "SCHSTORE.H"
       
    26 #include <schtask.h>
       
    27 #include "SCHLOG.h"
       
    28 
       
    29 // Constants
       
    30 const TInt KMinScheduleId = 0;
       
    31 const TInt KMaxSchedules = 25000;
       
    32 
       
    33 //Command line argument  
       
    34 _LIT(KCommandLine, "SYSSTARTSCHEXE");
       
    35 
       
    36 //SID of SysStart
       
    37 const TInt KSysStartSID = 0x10205C44; 
       
    38 
       
    39 
       
    40 #define UNUSED_VAR(a) a = a
       
    41 
       
    42 //
       
    43 // Construction/Destruction functions
       
    44 //
       
    45 
       
    46 CTaskScheduler::CTaskScheduler()
       
    47 :	iSchedules(CSchedule::Offset()), 
       
    48 	iClients(CClientProxy::Offset()),
       
    49 	iStartupStatePassNonCritical(EFalse)
       
    50 	{
       
    51 	}
       
    52 
       
    53 CTaskScheduler::~CTaskScheduler()
       
    54 	{
       
    55 	if (iBackupNotification)
       
    56 		{
       
    57 		iBackupNotification->DeRegisterBackupOperationObserver(*this);
       
    58 		}
       
    59 	delete iBackupNotification;
       
    60 	delete iBackupManager;
       
    61 	delete iNotifier;
       
    62 	delete iScheduleCriteriaManager;
       
    63 	delete iSchLogManager;
       
    64 	
       
    65 	//remove clients and schedules as well!!
       
    66 	TDblQueIter<CClientProxy> clientIter(iClients);
       
    67 	
       
    68 	clientIter.SetToFirst();
       
    69 	CClientProxy* client=NULL;
       
    70 	while ((client=clientIter++)!=NULL)
       
    71 		{
       
    72 			client->Remove();
       
    73 			delete client;
       
    74 		}
       
    75 	
       
    76 	TSglQueIter<CSchedule> schedIter(iSchedules);
       
    77 	
       
    78 	schedIter.SetToFirst();
       
    79 	CSchedule* schedule=NULL;
       
    80 	while ((schedule=schedIter++)!=NULL)
       
    81 		{
       
    82 			iSchedules.Remove(*schedule);
       
    83 			delete schedule;
       
    84 		}	
       
    85 	}
       
    86 
       
    87 void CTaskScheduler::ConstructL()
       
    88 	{
       
    89 	LOGSTRING("CTaskScheduler::ConstructL - Creating new schedule server log entry");
       
    90 
       
    91 	User::LeaveIfError(iFsSession.Connect());
       
    92 	iBackupManager = new(ELeave) CSchBackupManager(iFsSession);
       
    93 	iBackupManager->ConstructL();
       
    94 
       
    95 	iNotifier = CEnvironmentChangeNotifier::NewL(CActive::EPriorityHigh, TCallBack(EnvironmentChanged, this));
       
    96 	iNotifier->Start();
       
    97 
       
    98 	iScheduleCriteriaManager = CScheduleCriteriaManager::NewL(*this);
       
    99 
       
   100 	iSchLogManager = CSchLogManager::NewL(iFsSession);
       
   101 
       
   102 	LOGSTRING("CTaskScheduler::ConstructL - Restoring clients and schedules");
       
   103 	TRAPD(err, iBackupManager->RestoreL(iClients, iSchedules,*iSchLogManager));
       
   104 	if	(err != KErrNone) // the file's corrupt or something...
       
   105 		{
       
   106 		LOGSTRING2("CTaskScheduler::ConstructL - had to create new store because of error: %d", err);
       
   107 		iBackupManager->CreateEmptyBackupL();
       
   108 		}
       
   109 		
       
   110 	//checking the SID of the process which started the Task scheduler	
       
   111  	if (User::CreatorSecureId() == KSysStartSID)
       
   112 	 	{
       
   113 	    TInt argLen = User::CommandLineLength();
       
   114      	if (argLen)
       
   115 	         {
       
   116 	         HBufC* arg = HBufC::NewLC(argLen);
       
   117 	         TPtr argPtr = arg->Des();
       
   118 	         User::CommandLine(argPtr);
       
   119 	         argPtr.UpperCase();
       
   120 	         
       
   121 	 		 //Checking Comman dLine arg passed to it is same as in SSCForStartupMode0.rss
       
   122 	 		 //and checking for persisted schedules
       
   123 	         if((argPtr.Compare(KCommandLine) == 0) && iSchedules.IsEmpty())
       
   124 	             {
       
   125 	             //if no schedule leave
       
   126 				 User::Leave(KErrNone);
       
   127 	             }
       
   128 	 	      CleanupStack::PopAndDestroy(arg);
       
   129 	 	      }
       
   130          }
       
   131 
       
   132 	// Each client now contains a list of associated tasks. We need
       
   133 	// to now associate those tasks with specific schedules
       
   134 	CClientProxy* client;
       
   135 	TDblQueIter<CClientProxy> clientIter(iClients);
       
   136 	clientIter.SetToFirst();
       
   137 	while ((client = clientIter++) != NULL)
       
   138 		{
       
   139 		// Fetch an iterator for each task owned by this client
       
   140 		CScheduledTask* task;
       
   141 		TDblQueIter<CScheduledTask> taskIterator = client->TaskIterator();
       
   142 		taskIterator.SetToFirst();
       
   143 
       
   144 		// Iterate through all the tasks owned by this client, trying to find
       
   145 		// the corresponding schedules.
       
   146 		while ((task = taskIterator++) != NULL)
       
   147 			{
       
   148 			CSchedule* schedule = NULL;
       
   149 			schedule = Find(task->ScheduleId());
       
   150 			if (schedule)
       
   151 				{
       
   152 				TScheduledTask* taskRef = new(ELeave) TScheduledTask(*task,*client);
       
   153 				schedule->AddTask(*taskRef);
       
   154 				}
       
   155 			}
       
   156 		}
       
   157 	iBackupNotification = CBaBackupSessionWrapper::NewL();
       
   158 	iBackupNotification->RegisterBackupOperationObserverL(*this);
       
   159 	}
       
   160 
       
   161 CTaskScheduler* CTaskScheduler::NewL()
       
   162 	{
       
   163 	CTaskScheduler* self = CTaskScheduler::NewLC();
       
   164 	CleanupStack::Pop();
       
   165 	return self;	
       
   166 	}
       
   167 
       
   168 CTaskScheduler* CTaskScheduler::NewLC()
       
   169 	{
       
   170 	CTaskScheduler* self = new(ELeave) CTaskScheduler();
       
   171 	CleanupStack::PushL(self);
       
   172 	self->ConstructL();
       
   173 	return self;
       
   174 	}
       
   175 
       
   176 //
       
   177 // Client, Schedule and Task functions
       
   178 //
       
   179 
       
   180 CClientProxy* CTaskScheduler::AddClientL(const TDesC& aFilename, TInt aPriority)
       
   181 	{
       
   182 	//check we don't already have a client that will do...
       
   183 	TDblQueIter<CClientProxy> clientIter(iClients);
       
   184 	clientIter.SetToFirst();
       
   185 	CClientProxy* client=NULL;
       
   186 	while ((client=clientIter++)!=NULL)
       
   187 		{
       
   188 		if	(client->IsEqual(aFilename, aPriority))
       
   189 			return client;
       
   190 		}
       
   191 	client = CClientProxy::NewL(iFsSession, aFilename, aPriority,*iSchLogManager); 
       
   192 	iClients.Add(*client);
       
   193 	return client;
       
   194 	}
       
   195 
       
   196 void CTaskScheduler::AddScheduleL(CSchedule& aSchedule)
       
   197 	{
       
   198 	LOGSTRING3("CTaskScheduler::AddScheduleL - schedule: %S, %d", &aSchedule.Name(), aSchedule.Id());
       
   199 	iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationAdd, aSchedule);
       
   200 	iSchedules.AddLast(aSchedule);
       
   201 	LOGSTRING("CTaskScheduler::AddScheduleL - schedule added");
       
   202 	}
       
   203 
       
   204 void CTaskScheduler::EditScheduleL(TInt aScheduleHandle, CArrayFixFlat<TScheduleEntryInfo2>& aEntryList)
       
   205 	{
       
   206 	CSchedule* schedule = FindL(aScheduleHandle);
       
   207 
       
   208 	// remove schedule from condition manager before replacing entries to ensure 
       
   209 	// its deleted properly.
       
   210 	iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
       
   211 	schedule->ReplaceEntriesL(aEntryList);
       
   212 
       
   213 	TRAPD(err, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule));
       
   214 	if(err)
       
   215 		{
       
   216 		schedule->RemoveEntries();
       
   217 		User::Leave(err);
       
   218 		}
       
   219 	// recalculate due time only if schedule is enabled and has tasks to run	
       
   220 	if (IsScheduleReadyForUpdate(*schedule))
       
   221 		{
       
   222 		iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
       
   223 		}
       
   224 	}
       
   225 
       
   226 void CTaskScheduler::DoEditScheduleL(CSchedule& aSchedule, 
       
   227 							CArrayFixFlat<TTaskSchedulerCondition>& aConditionList,
       
   228 							const TTsTime& aDefaultTime)
       
   229 	{
       
   230 	aSchedule.ReplaceConditionsL(aConditionList);
       
   231 	
       
   232 	//Default Time is represented by a single entry class
       
   233 	CArrayFixFlat<TScheduleEntryInfo2>* entries 
       
   234 		= new(ELeave) CArrayFixFlat<TScheduleEntryInfo2>(1);
       
   235 	CleanupStack::PushL(entries);
       
   236 	TScheduleEntryInfo2 info;
       
   237 	info.SetStartTime(aDefaultTime);
       
   238 	info.SetInterval(1);
       
   239 	info.SetIntervalType(EDaily);
       
   240 	//validityperiod of 24 hours will ensure task is always run
       
   241 	info.SetValidityPeriod(60*24); 
       
   242 	entries->AppendL(info);
       
   243 	aSchedule.ReplaceEntriesL(*entries);
       
   244 	CleanupStack::Pop(entries);
       
   245 	
       
   246 	iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, aSchedule);
       
   247 	}
       
   248 
       
   249 void CTaskScheduler::EditScheduleL(TInt aScheduleHandle, 
       
   250 							CArrayFixFlat<TTaskSchedulerCondition>& aConditionList,
       
   251 							const TTsTime& aDefaultTime)
       
   252 	{
       
   253 	CSchedule* schedule = FindL(aScheduleHandle);
       
   254 
       
   255 	// remove schedule from condition manager before replacing entries to ensure 
       
   256 	// its deleted properly.
       
   257 	iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
       
   258 
       
   259 	TRAPD(err, DoEditScheduleL(*schedule, aConditionList, aDefaultTime));
       
   260 	if(err)
       
   261 		{
       
   262 		schedule->RemoveEntries();
       
   263 		schedule->RemoveConditions();
       
   264 		User::Leave(err);
       
   265 		}
       
   266 
       
   267 	// recalculate due time only if schedule is enabled and has tasks to run	
       
   268 	if (IsScheduleReadyForUpdate(*schedule))
       
   269 		{
       
   270 		iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
       
   271 		}
       
   272 	}	
       
   273 
       
   274 void CTaskScheduler::RemoveScheduleL(TInt aHandle)
       
   275 	{
       
   276 	CSchedule* schedule = FindL(aHandle);
       
   277 	LOGSTRING3("CTaskScheduler::RemoveScheduleL - schedule: %S, %d", &schedule->Name(), schedule->Id());
       
   278 	if (!schedule->HasTasks())
       
   279 		{
       
   280 		LOGSTRING("CTaskScheduler::RemoveScheduleL - schedule doesn't have any tasks, removing");
       
   281 		//remove schedule from timer
       
   282 		iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
       
   283 		DoRemoveL(schedule);
       
   284 		}
       
   285 	else
       
   286 		{
       
   287 		// Can't delete a schedule which has tasks
       
   288 		LOGSTRING("CTaskScheduler::RemoveScheduleL - schedule has tasks, can't delete");
       
   289 		User::Leave(KErrArgument);
       
   290 		}
       
   291 	}
       
   292 
       
   293 void CTaskScheduler::DisableScheduleL(TInt aHandle)
       
   294 	{
       
   295 	CSchedule* schedule = FindL(aHandle);
       
   296 	schedule->SetEnabled(EFalse);
       
   297 	iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule);
       
   298 	//remove schedule from timer as its disabled
       
   299 	iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
       
   300 	}
       
   301 
       
   302 void CTaskScheduler::EnableScheduleL(TInt aHandle)
       
   303 	{
       
   304 	CSchedule* schedule = FindL(aHandle);
       
   305 	schedule->SetEnabled(ETrue);
       
   306 	iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *schedule);
       
   307 
       
   308 	// recalculate due time only if schedule has tasks to run	
       
   309 	if ( IsScheduleReadyForUpdate(*schedule))
       
   310 		{
       
   311 		iScheduleCriteriaManager->ReplaceScheduleL(*schedule);
       
   312 		}
       
   313 	}
       
   314 
       
   315 void CTaskScheduler::ScheduleTaskL(CSchedule& aSchedule, CClientProxy& aClient)
       
   316 	{
       
   317 	// Backup the task
       
   318 	if	(aSchedule.Persists())
       
   319 		{
       
   320 		iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, aClient);
       
   321 		}
       
   322 	// if schedule is enabled then add schedule to timer.
       
   323 	if (aSchedule.Enabled() && IsStartupStateNonCritical())
       
   324 		{
       
   325 		iScheduleCriteriaManager->ReplaceScheduleL(aSchedule);
       
   326 		}		
       
   327 	}
       
   328 
       
   329 void CTaskScheduler::DeleteTaskL(TInt aScheduleHandle, TInt aTaskHandle)
       
   330 	{
       
   331 	CSchedule* schedule = FindL(aScheduleHandle);
       
   332 
       
   333 	TScheduledTask* task = schedule->Task(aTaskHandle);
       
   334 	if (!task)
       
   335 		{
       
   336 		LOGSTRING("CTaskScheduler::DeleteTaskL - task wasn't found");
       
   337 		User::Leave(KErrNotFound);
       
   338 		}
       
   339 
       
   340 	const CClientProxy& clientForTask = task->Client();
       
   341 	
       
   342 	// This deletes the task and removes the CScheduledTask
       
   343 	// from the CClientProxy's queue of tasks
       
   344 	task->RemoveInfo();
       
   345 
       
   346 	// This deletes the TScheduledTask defined above and removes it
       
   347 	// from CSchedule's queue of TScheduledTask's.
       
   348 	schedule->RemoveTask(task);
       
   349 	if (!schedule->HasTasks())	//i.e. it was the last task 
       
   350 		{
       
   351 		LOGSTRING("CTaskScheduler::DeleteTaskL - schedule doesn't have any more tasks left");
       
   352 		//remove scheule from timer as there are no more tasks
       
   353 		iScheduleCriteriaManager->RemoveSchedule(schedule->Id());
       
   354 		// If the schedule isn't persistent then we delete it (transient schedules only
       
   355 		// have one task).
       
   356 		if (!schedule->Persists())
       
   357 			DoRemoveL(schedule);
       
   358 		else
       
   359 			iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, clientForTask);		
       
   360 		}
       
   361 	else
       
   362 		{
       
   363 		// Backup the changes to the tasks. Although we are deleting a task, we are not actually
       
   364 		// deleting the client, so this is actually an edit operation.
       
   365 		if (schedule->Persists())
       
   366 			iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, clientForTask);
       
   367 		}
       
   368 	}
       
   369 
       
   370 //
       
   371 // Utility Functions
       
   372 //
       
   373 
       
   374 TInt CTaskScheduler::GenerateId()
       
   375 	{
       
   376 	TInt id = KMinScheduleId;
       
   377 	CSchedule* schedule = Find(id);
       
   378 	while (schedule!=NULL) 
       
   379 		{
       
   380 		id+=KScheduleIdDifferential;//=10 000
       
   381 		if ((id/KScheduleIdDifferential) > KMaxSchedules)
       
   382 			return KErrOverflow;
       
   383 		schedule = Find(id);
       
   384 		}
       
   385 	return id;
       
   386 	}
       
   387 
       
   388 void CTaskScheduler::DoRemoveL(CSchedule* aSchedule)
       
   389 	{
       
   390 	TRAPD(err, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationDelete, *aSchedule));
       
   391 	if	(err < KErrNone && err != KErrNotFound)
       
   392 		User::Leave(err);
       
   393 	iSchedules.Remove(*aSchedule);
       
   394 	delete aSchedule;
       
   395 	aSchedule = NULL;
       
   396 	}
       
   397 
       
   398 CSchedule* CTaskScheduler::FindL(TInt aHandle)
       
   399 	{
       
   400 	CSchedule* schedule = Find(aHandle);
       
   401 	if (!schedule)
       
   402 		User::Leave(KErrNotFound);
       
   403 	return schedule;
       
   404 	}
       
   405 
       
   406 CSchedule* CTaskScheduler::Find(TInt aHandle)
       
   407 	{
       
   408 	TSglQueIter<CSchedule> scheduleIter(iSchedules);
       
   409 	scheduleIter.SetToFirst();
       
   410 	CSchedule* schedule;
       
   411 	while ((schedule = scheduleIter++)!=NULL)
       
   412 		{
       
   413 		if (schedule->Id() == aHandle)
       
   414 			return schedule;
       
   415 		}
       
   416 	return NULL;
       
   417 	}
       
   418 
       
   419 // If aRefArray is NULL then only count it returned.
       
   420 TInt CTaskScheduler::GetScheduleRefsL(CArrayFixFlat<TSchedulerItemRef>* aRefArray, 
       
   421 									TScheduleFilter aFilter,
       
   422 									const RMessagePtr2& aMessage)
       
   423 	{
       
   424 	TInt count = 0;
       
   425 	TSglQueIter<CSchedule> iter(iSchedules);
       
   426 	iter.SetToFirst();
       
   427 	CSchedule* schedule = NULL;
       
   428 	while ((schedule = iter++) != NULL)
       
   429 		{
       
   430 		if(aFilter == EAllSchedules || (schedule->Enabled() && schedule->HasTasks()))
       
   431 			{
       
   432 			//only add information for schedules that the client has permission to alter
       
   433 			if(schedule->IsAccessAllowed(aMessage))
       
   434 				{
       
   435 				if(aRefArray)
       
   436 					{
       
   437 					TSchedulerItemRef ref;
       
   438 					ref.iHandle = schedule->Id();
       
   439 					ref.iName = schedule->Name();
       
   440 					aRefArray->AppendL(ref);	
       
   441 					}
       
   442 				count++;		
       
   443 				}
       
   444 			}
       
   445 		}
       
   446 	return count;				
       
   447 	}
       
   448 
       
   449 // If aRefArray is NULL then only count it returned.
       
   450 TInt CTaskScheduler::GetTaskRefsL(CArrayFixFlat<TSchedulerItemRef>* aRefArray, 
       
   451 									TScheduleFilter aScheduleFilter,
       
   452 									TTaskFilter aTaskFilter,
       
   453 									CClientProxy* aClient,
       
   454 									const RMessagePtr2& aMessage)
       
   455 	{
       
   456 	TInt count = 0;
       
   457 	TSglQueIter<CSchedule> iter(iSchedules);
       
   458 	iter.SetToFirst();
       
   459 	CSchedule* schedule = NULL;
       
   460 	while ((schedule = iter++) != NULL)
       
   461 		{
       
   462 		if(aScheduleFilter == EAllSchedules || (schedule->Enabled() && schedule->HasTasks()))
       
   463 			{
       
   464 			//only add information for schedules that the client has permission to alter
       
   465 			if(schedule->IsAccessAllowed(aMessage))
       
   466 				{
       
   467 				TSglQueIter<TScheduledTask> taskIter(*(schedule->Tasks()));
       
   468 				taskIter.SetToFirst();
       
   469 				TScheduledTask* task;
       
   470 				while ((task=taskIter++)!=NULL)
       
   471 					{
       
   472 					if (aTaskFilter==EAllTasks||&task->Client() == aClient) // This pointer comparison is a bit rubbish.  Change?
       
   473 						{
       
   474 						if(aRefArray)
       
   475 							{
       
   476 							TTaskInfo info = task->Info();
       
   477 							TSchedulerItemRef ref;
       
   478 							ref.iHandle = info.iTaskId;
       
   479 							ref.iName = info.iName;
       
   480 							aRefArray->AppendL(ref);
       
   481 							}
       
   482 						count++;
       
   483 						}
       
   484 					}
       
   485 				}
       
   486 			}
       
   487 		}
       
   488 	return count;				
       
   489 	}
       
   490 	
       
   491 
       
   492 //
       
   493 // Schedule Execution functions
       
   494 //
       
   495 
       
   496 // A schedule is ready to be run
       
   497 void CTaskScheduler::DueTaskNotifyL(TInt aScheduleHandle)
       
   498 	{
       
   499 	CSchedule* schedule = FindL(aScheduleHandle);
       
   500 	//NotifyTasks() also removes tasks from the schedule if there are no 
       
   501 	//repeats left.
       
   502 	schedule->NotifyTasks(); 
       
   503 
       
   504 	if (!schedule->HasTasks())
       
   505 		{
       
   506 		// remove schedule.
       
   507 		TRAPD(ignore, DoRemoveL(schedule));
       
   508 		//??error only occurs in relation to persistence!! Do something.  
       
   509         UNUSED_VAR(ignore);
       
   510 		}
       
   511 	else
       
   512 		{
       
   513 		__ASSERT_ALWAYS(IsStartupStateNonCritical(), User::Invariant());
       
   514 		iScheduleCriteriaManager->ReplaceScheduleL(*schedule,EConditionAndTime,ETrue);
       
   515 		}
       
   516 
       
   517 	// Execute all clients.  This method doesn't leave as all errors are either
       
   518 	// logged in the log engine or handled elsewhere.
       
   519 	ExecuteClients();
       
   520 	}
       
   521 
       
   522 //	Go through all clients, executing their tasks
       
   523 void CTaskScheduler::ExecuteClients(TBool aUpdateClient)
       
   524 	{
       
   525 	if ((BUROperationInProgress() == EBUROperationNoActivity) || !aUpdateClient)
       
   526 		{
       
   527 		TDblQueIter<CClientProxy> clientIter(iClients);
       
   528 		clientIter.SetToFirst();
       
   529 		CClientProxy* client;
       
   530 		while( (client = clientIter++) != NULL)
       
   531 			{
       
   532 			// Does this client have anything ready to run?
       
   533 			if	(client->IsReadyToExecute())
       
   534 				{
       
   535 				client->ExecuteTasks();
       
   536 				// Clears the 'IsReadyToExecute' flag...
       
   537 				client->RemoveDueTasks();
       
   538 				}
       
   539 			}
       
   540 		if (aUpdateClient)	
       
   541 			{
       
   542 			// Update the store file now
       
   543 			UpdateClients();	
       
   544 			}
       
   545 		}
       
   546 	else
       
   547 		{
       
   548 		// Sets the flag to trigger delayed store operation when BUR ends
       
   549 		iTaskExecutedDuringBUR = ETrue;
       
   550 		}
       
   551 	}
       
   552 
       
   553 //	Go through all clients, update the store file with modified client info
       
   554 void CTaskScheduler::UpdateClients()
       
   555 	{
       
   556 	// iterate the client list to perform delayed update of the store file
       
   557 	TDblQueIter<CClientProxy> clientIter(iClients);
       
   558 	clientIter.SetToFirst();
       
   559 	CClientProxy* client;
       
   560 	while( (client = clientIter++) != NULL)
       
   561 		{
       
   562 		if	(!client->Users())
       
   563 			{
       
   564 			// Remove from store
       
   565 			TRAPD(ignore, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationDelete, *client));
       
   566 			//?? if ignore is not KErrNone then there is a problem with the store
       
   567             UNUSED_VAR(ignore);
       
   568 			// Remove client & delete it
       
   569 			client->Remove();
       
   570 			delete client;
       
   571 			}
       
   572 		else
       
   573 			{
       
   574 			// Update this clients data in the store...
       
   575 			TRAPD(ignore, iBackupManager->PerformStoreOperationL(CSchBackupManager::ESchBackupOperationEdit, *client));
       
   576 
       
   577 			//?? if ignore is not KErrNone then there is a problem with the store
       
   578             UNUSED_VAR(ignore);
       
   579 			}
       
   580 		}
       
   581 	}
       
   582 	
       
   583 //
       
   584 // Environment change functions
       
   585 //
       
   586 
       
   587 TInt CTaskScheduler::EnvironmentChanged(TAny* aScheduler)
       
   588 	{
       
   589 	CTaskScheduler* self = reinterpret_cast<CTaskScheduler*>(aScheduler);
       
   590 	self->HandleEnvironmentChange();
       
   591 	return KErrNone;
       
   592 	}
       
   593 
       
   594 void CTaskScheduler::HandleEnvironmentChange()
       
   595 	{
       
   596 	// If staged startup still in critical region, can safely
       
   597 	// ignore system time change.
       
   598 	if (!IsStartupStateNonCritical())
       
   599 		{
       
   600 		return;
       
   601 		}
       
   602 
       
   603 	TInt changes=iNotifier->Change();
       
   604 	if	(changes & EChangesSystemTime)
       
   605 		{
       
   606 #ifdef __SCHLOGGING__
       
   607 		{
       
   608 		TTime time;
       
   609 		time.HomeTime();
       
   610 		TDateTime due(time.DateTime());
       
   611 		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());
       
   612 		}
       
   613 #endif
       
   614 
       
   615 
       
   616 		// Cannot use AddSchedulesToTimerL() because this method
       
   617 		// uses the non-condition version of ReplaceScheduleL.
       
   618 		TSglQueIter<CSchedule> scheduleIter(iSchedules);
       
   619 		scheduleIter.SetToFirst();
       
   620 		CSchedule* schedule = NULL;
       
   621 		while ((schedule=scheduleIter++)!=NULL)
       
   622 			{
       
   623 			if(IsScheduleReadyForUpdate(*schedule))
       
   624 				{
       
   625 				TRAPD(err, iScheduleCriteriaManager->ReplaceScheduleL(*schedule, EOnlyTime));
       
   626                 UNUSED_VAR(err);
       
   627 				}
       
   628 			}
       
   629 		}
       
   630 	}
       
   631 
       
   632 void CTaskScheduler::AddSchedulesToTimerL()
       
   633 	{
       
   634 	if (!IsStartupStateNonCritical())
       
   635 		{
       
   636 		return; // not ready
       
   637 		}
       
   638 
       
   639 	TInt ret = KErrNone;
       
   640 
       
   641 	TSglQueIter<CSchedule> scheduleIter(iSchedules);
       
   642 	scheduleIter.SetToFirst();
       
   643 	CSchedule* schedule = NULL;
       
   644 	while ((schedule=scheduleIter++)!=NULL)
       
   645 		{
       
   646 		if(IsScheduleReadyForUpdate(*schedule))
       
   647 			{
       
   648 			TRAPD(err, iScheduleCriteriaManager->ReplaceScheduleL(*schedule));
       
   649 			if (err != KErrNone)
       
   650 				{
       
   651 				ret = err;
       
   652 				}
       
   653 			}
       
   654 		}
       
   655 	User::LeaveIfError(ret);
       
   656 	}
       
   657 	
       
   658 void CTaskScheduler::CleanupScheduledTasksL()
       
   659 	{
       
   660 	RFs fs;
       
   661 	_LIT(KTempFilePath, "_:\\private\\10005399\\*.tmp");
       
   662 	TBuf<32> filePath(KTempFilePath);
       
   663 
       
   664 	filePath[0] = RFs::GetSystemDriveChar();	
       
   665 	
       
   666 	fs.Connect();
       
   667 	CleanupClosePushL(fs);
       
   668 	
       
   669 	CFileMan* fileMan = CFileMan::NewL(fs);
       
   670 	CleanupStack::PushL(fileMan);
       
   671 
       
   672 	//Delete all temporary files in the private folder	
       
   673 	fileMan->Delete(filePath,0);
       
   674 	
       
   675 	//Pop and destroy fs and fileMan  
       
   676 	//This will call fs.Close() so no need to call it explicitly
       
   677 	CleanupStack::PopAndDestroy(2); 
       
   678 	}
       
   679 
       
   680 /**
       
   681 CSchStartupStateMgr calls this to notify startup state changes of
       
   682 interest.
       
   683 
       
   684 @internalComponent
       
   685 */
       
   686 void CTaskScheduler::ProcessSSAEventL(TStartupStateIdentifier aKnownState)
       
   687 	{
       
   688 	LOGSTRING2("ProcessSSAEventL receive SS 0x%x", aKnownState);
       
   689 
       
   690 	if (! IsStartupStateNonCritical() &&
       
   691 		(aKnownState >= KSchFinalStartupState))
       
   692 		{
       
   693 		iStartupStatePassNonCritical = ETrue;
       
   694 		CleanupScheduledTasksL();
       
   695 		AddSchedulesToTimerL();
       
   696 		}
       
   697 	}
       
   698 
       
   699 /**
       
   700 Returns ETrue if Start-up State is NonCritical
       
   701 */
       
   702 TBool CTaskScheduler::IsStartupStateNonCritical()
       
   703 	{
       
   704 	return iStartupStatePassNonCritical;
       
   705 	}
       
   706 
       
   707 /**
       
   708 Check schedule is valid
       
   709 */
       
   710 TBool CTaskScheduler::IsScheduleReadyForUpdate(CSchedule& aSchedule)
       
   711 	{
       
   712 	if(aSchedule.IsUpdatable() && IsStartupStateNonCritical())
       
   713 		return 	ETrue;		
       
   714 	else
       
   715 		return EFalse;
       
   716 	}
       
   717 
       
   718 /**
       
   719 babackup server calls this to notify backup operations. The attributes are read and translated to determine
       
   720 which operation is actually in progress.  
       
   721 @internalComponent
       
   722 */
       
   723 void CTaskScheduler::HandleBackupOperationEventL(const TBackupOperationAttributes& aBackupOperationAttributes)
       
   724 	{
       
   725 	TBUROperation type;
       
   726 
       
   727 	// determine the operation type (backup or restore)
       
   728 	switch(aBackupOperationAttributes.iFileFlag)	
       
   729 		{
       
   730 		case MBackupObserver::EReleaseLockReadOnly:
       
   731 			type = EBUROperationBackup;
       
   732 			break;
       
   733 		case MBackupObserver::EReleaseLockNoAccess:
       
   734 			type = EBUROperationRestore;
       
   735 			break;
       
   736 		case MBackupObserver::ETakeLock:
       
   737 			// No information is passed from babackup server, so we need to depend on our own memory
       
   738 			type = iBUROperationInProgress;
       
   739 			break;
       
   740 		default:
       
   741 			type = EBUROperationNoActivity;
       
   742 			break;
       
   743 		}
       
   744 		
       
   745 	// determine the operation status (e.g. starting, ending)
       
   746 	switch(aBackupOperationAttributes.iOperation)
       
   747 		{
       
   748 		case EStart:
       
   749 			BURBeginningL(type);
       
   750 			break;
       
   751 		case EEnd:
       
   752 			BURCompleteL(type, EBUROperationSuccess);
       
   753 			break;
       
   754 		case EAbort:
       
   755 			BURCompleteL(type, EBUROperationAbort);
       
   756 			break;
       
   757 		default:
       
   758 			break;
       
   759 		}
       
   760 	}
       
   761 
       
   762 
       
   763 /**
       
   764 This function is called to notify when a Backup or Restore operation is commencing.
       
   765 
       
   766 @internalComponent
       
   767 */
       
   768 void CTaskScheduler::BURBeginningL(TBUROperation aOperationType)
       
   769 {
       
   770 	// This will stop the API calls that directly modify the store file
       
   771 	iBUROperationInProgress	= aOperationType;
       
   772 	
       
   773 	//cancel background compaction of store during backup/restore	
       
   774 	iBackupManager->Cancel();
       
   775 }
       
   776 
       
   777 
       
   778 /**
       
   779 This function is called to notify when a Backup or Restore operation is finished.
       
   780 
       
   781 @internalComponent
       
   782 */
       
   783 void CTaskScheduler::BURCompleteL(TBUROperation aOperationType, TBUROperationResult aBURResult)
       
   784 {
       
   785 	// If there is a successful restore, this means that we have a different store file then we were using 
       
   786 	// so we have to internalize and use that file. In any other case, we can proceed with the delayed 
       
   787 	// updates to the old file
       
   788 	if ((aOperationType == EBUROperationRestore)&&(aBURResult == EBUROperationSuccess))
       
   789 		{
       
   790 		LOGSTRING("CTaskScheduler::BURCompleteL - Restoring clients and schedules after successful restore");
       
   791 
       
   792 		//First check whether any task expires during the restore process now that this is completed
       
   793 		if (iTaskExecutedDuringBUR)	
       
   794 			{
       
   795 			// performed the delayed task execution but with no externalizing as we dont want to modify
       
   796 			// the just restored file as after the delayed execution, all persistent schedule will be removed
       
   797 			ExecuteClients(EFalse);
       
   798 			iTaskExecutedDuringBUR=EFalse;			
       
   799 			}
       
   800 		
       
   801 		// Now remove existing persistent schedules, tasks and clients
       
   802 		TSglQueIter<CSchedule> scheduleIter(iSchedules);
       
   803 		scheduleIter.SetToFirst();
       
   804 		CSchedule* schedule;
       
   805 		while ((schedule = scheduleIter++)!=NULL)
       
   806 			{
       
   807 			if (schedule->Persists())
       
   808 				{
       
   809 				iSchedules.Remove(*schedule);
       
   810 				schedule->RemoveTasks(ETrue);
       
   811 				delete schedule; 
       
   812 				}
       
   813 			}
       
   814 
       
   815 		CClientProxy* client;
       
   816 		TDblQueIter<CClientProxy> clientIter(iClients);
       
   817 		
       
   818 		// remove clients which don't have any associated tasks left (tasks in persistent schedules are
       
   819 		// already removed, but the client might have transient schedules as well)
       
   820 		clientIter.SetToFirst();
       
   821 		while ((client = clientIter++) != NULL)
       
   822 			{
       
   823 			TDblQueIter<CScheduledTask> taskIter = client->TaskIterator();
       
   824 			taskIter.SetToFirst();
       
   825 			
       
   826 			// remove client if no more tasks
       
   827 			if (taskIter++ == NULL)
       
   828 				{
       
   829 				client->Remove();
       
   830 				delete client; // removes associated tasks
       
   831 				}
       
   832 			else
       
   833 				{
       
   834 				//remove any persisted task and if the client only has persisted task, remove client as well
       
   835 				taskIter.SetToFirst();
       
   836 				CScheduledTask* task;
       
   837 				TInt taskCount=0;
       
   838 				TInt persistCount=0;
       
   839 				while ((task = taskIter++) != NULL)
       
   840 					{
       
   841 					taskCount++;
       
   842 					if (task->Persists())
       
   843 						{
       
   844 						persistCount++;
       
   845 						client->RemoveTask(task);
       
   846 						}
       
   847 					}
       
   848 				//if after removing the persist tasks, there are no more other tasks, we can remove the client too						
       
   849 				if (taskCount==persistCount)
       
   850 					{
       
   851 					client->Remove();
       
   852 					delete client;
       
   853 					}					
       
   854 				}
       
   855 			}
       
   856 		
       
   857 		// now re-read the clients and schedules from the restored store file
       
   858 		TRAPD(err, iBackupManager->RestoreL(iClients, iSchedules,*iSchLogManager,ETrue));
       
   859 
       
   860 		if	(err != KErrNone) // the file's corrupt or something...
       
   861 			{
       
   862 			LOGSTRING2("CTaskScheduler::BURCompleteL - had to create new store because of error: %d", err);
       
   863 			iBackupManager->CreateEmptyBackupL();
       
   864 			}
       
   865 
       
   866 			
       
   867 		// Each client now contains a list of associated tasks. We need
       
   868 		// to now associate those tasks with specific schedules
       
   869 		clientIter.SetToFirst();
       
   870 		while ((client = clientIter++) != NULL)
       
   871 			{
       
   872 			// Fetch an iterator for each task owned by this client
       
   873 			CScheduledTask* task;
       
   874 			TDblQueIter<CScheduledTask> taskIterator = client->TaskIterator();
       
   875 			taskIterator.SetToFirst();
       
   876 
       
   877 			// Iterate through all the tasks owned by this client, trying to find
       
   878 			// the corresponding schedules.
       
   879 			while ((task = taskIterator++) != NULL)
       
   880 				{
       
   881 				TSglQueIter<CSchedule> persScheduleIter(iSchedules);
       
   882 				persScheduleIter.SetToFirst();
       
   883 				CSchedule* persSchedule;
       
   884 				while ((persSchedule = persScheduleIter++)!=NULL)
       
   885 					{
       
   886 					if ((persSchedule->Persists())&&(persSchedule->Id() == task->ScheduleId()))
       
   887 						{
       
   888 						TScheduledTask* taskRef = new(ELeave) TScheduledTask(*task,*client);
       
   889 						persSchedule->AddTask(*taskRef);
       
   890 						}
       
   891 					}
       
   892 				}
       
   893 			}
       
   894 		
       
   895 		// Activate the scheduler with the new schedules
       
   896 		AddSchedulesToTimerL();	
       
   897 		}
       
   898 	else
       
   899 		{
       
   900 		if (iTaskExecutedDuringBUR)	
       
   901 			{
       
   902 			iBUROperationInProgress	= EBUROperationNoActivity;		
       
   903 			iTaskExecutedDuringBUR = EFalse;
       
   904 			// performed the delayed task execution
       
   905 			ExecuteClients();
       
   906 			}	
       
   907 		}	
       
   908 	
       
   909 	// BUR operation is completed
       
   910 	iBUROperationInProgress	= EBUROperationNoActivity;		
       
   911 	iTaskExecutedDuringBUR = EFalse;
       
   912 }