os/ossrv/genericservices/taskscheduler/SCHSVR/SCHCLI.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericservices/taskscheduler/SCHSVR/SCHCLI.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,410 @@
     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 <logwraplimits.h>
    1.21 +#include <logwrap.h>
    1.22 +#include <schtask.h>
    1.23 +
    1.24 +
    1.25 +// User includes
    1.26 +#include "SCHCLI.H"
    1.27 +#include "SchLogger.h"
    1.28 +#include "SCHEXEC.H"
    1.29 +#include "SCHLOG.h"
    1.30 +
    1.31 +
    1.32 +// Constants
    1.33 +#define KEllipsis 0x2026
    1.34 +const TInt KTaskArrayGranularity = 1;
    1.35 +_LIT(KTaskNameSeparator, ", ");
    1.36 +
    1.37 +
    1.38 +
    1.39 +//
    1.40 +// CClientProxy
    1.41 +//
    1.42 +CClientProxy::CClientProxy(RFs& aFsSession, CSchLogManager& aLogManager)
    1.43 +:	iFsSession(aFsSession), 
    1.44 +	iTasks(CScheduledTask::Offset()),
    1.45 +	iSchLogManager(aLogManager)
    1.46 +	{
    1.47 +	}
    1.48 +
    1.49 +CClientProxy::CClientProxy(RFs& aFsSession, TInt aPriority, CSchLogManager& aLogManager)
    1.50 +:	iFsSession(aFsSession), 
    1.51 +	iTasks(CScheduledTask::Offset()),
    1.52 +	iSchLogManager(aLogManager)
    1.53 +	{
    1.54 +	iPriLink.iPriority = aPriority;
    1.55 +	}
    1.56 +
    1.57 +CClientProxy::~CClientProxy()
    1.58 +	{
    1.59 +	LOGSTRING("CClientProxy::~CClientProxy - start");
    1.60 +
    1.61 +	TDblQueIter<CScheduledTask> taskIter(iTasks);
    1.62 +	taskIter.SetToFirst();
    1.63 +	CScheduledTask* task;
    1.64 +	while ((task = taskIter++) != NULL)
    1.65 +		{
    1.66 +		RemoveTask(task);
    1.67 +		}
    1.68 +	delete iFileName;
    1.69 +	LOGSTRING("CClientProxy::~CClientProxy - end");
    1.70 +	} 
    1.71 +
    1.72 +void CClientProxy::ConstructL(const TDesC& aFileName)
    1.73 +	{
    1.74 +	iFileName = aFileName.AllocL();
    1.75 +	}
    1.76 +
    1.77 +CClientProxy* CClientProxy::NewL(RFs& aFsSession, 
    1.78 +								const TDesC& aFileName, 
    1.79 +								TInt aPriority,
    1.80 +								CSchLogManager& aLogManager)
    1.81 +	{
    1.82 +	CClientProxy* self = new(ELeave) CClientProxy(aFsSession, aPriority,aLogManager);
    1.83 +	CleanupStack::PushL(self);
    1.84 +	self->ConstructL(aFileName);
    1.85 +	CleanupStack::Pop();
    1.86 +	return self;
    1.87 +	}
    1.88 +
    1.89 +CClientProxy* CClientProxy::NewL(RFs& aFsSession, 
    1.90 +								RReadStream& aStream,
    1.91 +								CSchLogManager& aLogManager)
    1.92 +	{
    1.93 +	CClientProxy* self = new(ELeave) CClientProxy(aFsSession,aLogManager);
    1.94 +	CleanupStack::PushL(self);
    1.95 +	aStream >> *self;
    1.96 +	CleanupStack::Pop();
    1.97 +	return self;
    1.98 +	}
    1.99 +
   1.100 +TBool CClientProxy::IsEqual(const TDesC& aFilename, TInt aPriority) const
   1.101 +	{
   1.102 +	// Equality here means: same DLL filename, DLL ordinal & priority
   1.103 +	return ((*iFileName == aFilename) && (iPriLink.iPriority == aPriority));
   1.104 +	}
   1.105 +
   1.106 +void CClientProxy::AddTask(CScheduledTask& aTask)
   1.107 +	{
   1.108 +	LOGSTRING("CClientProxy::AddTask - start");
   1.109 +	iTasks.Add(aTask);
   1.110 +	iUsers++;
   1.111 +	LOGSTRING("CClientProxy::AddTask - end");
   1.112 +	}
   1.113 +
   1.114 +void CClientProxy::RemoveTask(CScheduledTask* aTask)
   1.115 +	{
   1.116 +	LOGSTRING("CClientProxy::RemoveTask - start");
   1.117 +	iUsers--;
   1.118 +	aTask->Remove();
   1.119 +	delete aTask;
   1.120 +	LOGSTRING("CClientProxy::RemoveTask - end");
   1.121 +	}
   1.122 +
   1.123 +//
   1.124 +static void BuildTaskErrorMessage(const CArrayPtr<CScheduledTask>& aTasks, TDes& aErrorMessage)
   1.125 +//
   1.126 +//	Establish the names of all the tasks that potentially might fail
   1.127 +//	when executing the task. This is done *before* actually executing the
   1.128 +//	tasks as its not possible to discern (at failure time) which tasks
   1.129 +//	were actually executing (because we don't know at what time the task
   1.130 +//	executor was spawned).
   1.131 +//
   1.132 +	{
   1.133 +	const TInt count = aTasks.Count();
   1.134 +	for(TInt i=0; i<count; i++)
   1.135 +		{
   1.136 +		const TDesC& taskName = aTasks.At(i)->Info().iName;
   1.137 +		if	(aErrorMessage.Length() + taskName.Length() > KLogMaxSubjectLength - KTaskNameSeparator().Length())
   1.138 +			{
   1.139 +			// The task name that still needs adding to the subject line (of the
   1.140 +			// log entry) is too big to fit within KLogCallEventTypeUid characters.
   1.141 +			// Trim the task name so that it will fit, and append the ellipsis
   1.142 +			// character to indicate that more tasks were present but unable to be
   1.143 +			// shown.
   1.144 +			TInt lengthOfTaskNameToAccept = (KLogMaxSubjectLength - aErrorMessage.Length()) - KTaskNameSeparator().Length();
   1.145 +			if	(lengthOfTaskNameToAccept <= 0)
   1.146 +				break;
   1.147 +			aErrorMessage += taskName.Left(lengthOfTaskNameToAccept);
   1.148 +			aErrorMessage.Append(KEllipsis);
   1.149 +			
   1.150 +			// Exit the 'for' loop as there isn't any more room to hold subsequent
   1.151 +			// tasks that potentially failed...
   1.152 +			break;
   1.153 +			}
   1.154 +		else
   1.155 +			{
   1.156 +			aErrorMessage += taskName;
   1.157 +			}
   1.158 +
   1.159 +		if	(i<count-1) // not the last taskName
   1.160 +			{
   1.161 +			// Append a comma
   1.162 +			aErrorMessage += KTaskNameSeparator;
   1.163 +			}
   1.164 +		}
   1.165 +	}
   1.166 +	
   1.167 +void CClientProxy::ExecuteTasks()
   1.168 +	{
   1.169 +	// generate an array of due tasks
   1.170 +	CArrayPtr<CScheduledTask>* tasks = NULL;
   1.171 +	TRAPD(err, tasks = DueTasksL());
   1.172 +	if(err)
   1.173 +		{
   1.174 +		iSchLogManager.LogError(err);
   1.175 +		return;
   1.176 +		}
   1.177 +	
   1.178 +	// Create the task error message, just in case an error occurs
   1.179 +	TBuf<KLogMaxSubjectLength> errorMessage;
   1.180 +	BuildTaskErrorMessage(*tasks, errorMessage);
   1.181 +
   1.182 +	TInt error =DoExecuteTasks(*tasks, errorMessage);
   1.183 +	if(error)
   1.184 +		iSchLogManager.LogError(errorMessage,error);
   1.185 +	delete tasks;
   1.186 +	}
   1.187 +
   1.188 +TInt CClientProxy::DoExecuteTasks(const CArrayPtr<CScheduledTask>& aTasks,
   1.189 +									const TDesC& aErrorMessage)
   1.190 +	{
   1.191 +	// Generate a unique task name
   1.192 +	TTime timenow;
   1.193 +	timenow.UniversalTime();
   1.194 +	TBuf<24> filename; // 20 is the longest decimal char length of a 64-bit number + 4 for extension
   1.195 +	filename.Format(_L("%Ld.tmp"),timenow.Int64());
   1.196 +	
   1.197 +	// Save & perform execution
   1.198 +	TRAPD(error, DoExecuteTasksL(aTasks, filename, aErrorMessage));
   1.199 +
   1.200 +	if (error != KErrNone)
   1.201 +		{
   1.202 +		LOGSTRING2("CClientProxy::ExecuteTasksL - attempted to execute tasks, error was %d", error);
   1.203 +		// Cleanup the file that was created if the execution fails in any way. Note
   1.204 +		// that it might not have been created
   1.205 +
   1.206 +		// If a debug build - record error
   1.207 +		TInt fileDeleteErr=iFsSession.Delete(filename);
   1.208 +		if (fileDeleteErr != KErrNone)
   1.209 +			{
   1.210 +			LOGSTRING2("CClientProxy::DoExecuteTasks - Failed to delete file. Error = %d", fileDeleteErr);
   1.211 +			}
   1.212 +		}
   1.213 +	return error;
   1.214 +	}
   1.215 +
   1.216 +void CClientProxy::DoExecuteTasksL(const CArrayPtr<CScheduledTask>& aTasks, 
   1.217 +									const TDesC& aFileName,
   1.218 +									const TDesC& aErrorMessage)
   1.219 +	{
   1.220 +	// Save the tasks to disk
   1.221 +	SaveTasksToFileL(aTasks, aFileName);
   1.222 +	
   1.223 +	// Spawn the task executor active object (deletes itself upon completion)
   1.224 +	CTaskExecutor* executor = CTaskExecutor::NewLC(aErrorMessage,aFileName,*iFileName,iSchLogManager);
   1.225 +	executor->ExecuteL();
   1.226 +	CleanupStack::Pop(executor);
   1.227 +	// Don't delete executor here as it does it itself once 
   1.228 +	// the task has finished (delete this in its RunL() )
   1.229 +	}
   1.230 +
   1.231 +
   1.232 +CArrayPtr<CScheduledTask>* CClientProxy::DueTasksL()
   1.233 +//
   1.234 +//	Returns a copy of any due tasks
   1.235 +//
   1.236 +	{
   1.237 +	CArrayPtrFlat<CScheduledTask>* tasks = new(ELeave)CArrayPtrFlat<CScheduledTask> (KTaskArrayGranularity);
   1.238 +	CleanupStack::PushL(tasks);
   1.239 +	TDblQueIter<CScheduledTask> taskIter(iTasks);
   1.240 +	taskIter.SetToFirst();
   1.241 +	CScheduledTask* task;
   1.242 +	while ((task=taskIter++)!=NULL)
   1.243 +		{
   1.244 +		if (task->Due())
   1.245 +			{
   1.246 +			tasks->AppendL(task);
   1.247 +			}
   1.248 +		}
   1.249 +	CleanupStack::Pop(tasks);
   1.250 +	return tasks;
   1.251 +	}
   1.252 +	
   1.253 +
   1.254 +CFileStore* CClientProxy::CreateStoreL(const TDesC& aName,TUint aFileMode)
   1.255 +//
   1.256 +//	To make the code clearer - called within a trap frame that shouldn't leave anything 
   1.257 +//	on cleanup stack.
   1.258 +//
   1.259 +	{
   1.260 +	CFileStore* store = CDirectFileStore::CreateLC(iFsSession, aName, aFileMode);
   1.261 +	CleanupStack::Pop(store);
   1.262 +	return store;
   1.263 +	}
   1.264 +
   1.265 +void CClientProxy::SaveTasksToFileL(const CArrayPtr<CScheduledTask>& aTasks, const TDesC& aFileName)
   1.266 +	{
   1.267 +	LOGSTRING("CClientProxy::SaveTasksToFileL - start");
   1.268 +
   1.269 +	// Create the file store
   1.270 +	LOGSTRING("CClientProxy::SaveTasksToFileL - creating store");
   1.271 +	CFileStore* store = CreateStoreL(aFileName, EFileWrite);
   1.272 +	CleanupStack::PushL(store);
   1.273 +
   1.274 +	// Save the actual tasks to the store
   1.275 +	LOGSTRING("CClientProxy::SaveTasksToFileL - saving tasks");
   1.276 +	SaveTasksL(*store, aTasks);
   1.277 +	CleanupStack::PopAndDestroy(store);
   1.278 +
   1.279 +	LOGSTRING("CClientProxy::SaveTasksToFileL - end");
   1.280 +	}
   1.281 +
   1.282 +void CClientProxy::SaveTasksL(CFileStore& aStore, const CArrayPtr<CScheduledTask>& aTasks)
   1.283 +	{
   1.284 +	LOGSTRING("CClientProxy::SaveTasksL - start");
   1.285 +	aStore.SetTypeL(KDirectFileStoreLayoutUid);	
   1.286 +
   1.287 +	// Save the tasks
   1.288 +	RStoreWriteStream outstream;
   1.289 +	TStreamId id = outstream.CreateLC(aStore);
   1.290 +	const TInt count = aTasks.Count();
   1.291 +	LOGSTRING2("CClientProxy::SaveTasksL - saving %d tasks", count);
   1.292 +	outstream.WriteInt32L(count);
   1.293 +	for (TInt i=0;i<count;i++)
   1.294 +		{
   1.295 +		CScheduledTask* task = aTasks.At(i);
   1.296 +		task->ExternalizeL(outstream);
   1.297 +		} 
   1.298 +	outstream.CommitL();
   1.299 +	CleanupStack::PopAndDestroy(); // outstream
   1.300 +
   1.301 +	aStore.SetRootL(id);							
   1.302 +	aStore.CommitL();							
   1.303 +	LOGSTRING("CClientProxy::SaveTasksL - end");
   1.304 +	}
   1.305 +
   1.306 +void CClientProxy::RemoveDueTasks()
   1.307 +	{
   1.308 +	LOGSTRING("CClientProxy::RemoveDueTasks - start");
   1.309 +
   1.310 +	TDblQueIter<CScheduledTask> taskIter(iTasks);
   1.311 +	taskIter.SetToFirst();
   1.312 +	CScheduledTask* task;
   1.313 +	//
   1.314 +	while ((task=taskIter++)!=NULL)
   1.315 +		{
   1.316 +		if (task->Due())
   1.317 +			{
   1.318 +			LOGSTRING3("CClientProxy::RemoveDueTasks - found due task %S, %d", &task->Info().iName, task->Info().iTaskId);
   1.319 +
   1.320 +			if	(!task->Info().iRepeat)
   1.321 +				{
   1.322 +				LOGSTRING("CClientProxy::RemoveDueTasks - task has no repeats left - it's being removed");
   1.323 +				RemoveTask(task);
   1.324 +				}
   1.325 +			else
   1.326 +				{
   1.327 +				LOGSTRING("CClientProxy::RemoveDueTasks - task still has some repeats, setting as 'no longer due'");
   1.328 +				task->SetDue(EFalse);
   1.329 +				}
   1.330 +			}
   1.331 +		}
   1.332 +	iReadyToExecute = EFalse;
   1.333 +	LOGSTRING("CClientProxy::RemoveDueTasks - end");
   1.334 +	}
   1.335 +
   1.336 +void CClientProxy::TransferTasks(CClientProxy& aTargetClient)
   1.337 +	{
   1.338 +	TDblQueIter<CScheduledTask> taskIter(iTasks);
   1.339 +	taskIter.SetToFirst();
   1.340 +	CScheduledTask* task;
   1.341 +	while ((task=taskIter++)!=NULL)
   1.342 +		{
   1.343 +		task->Remove();
   1.344 +		aTargetClient.AddTask(*task);
   1.345 +		}
   1.346 +	}
   1.347 +
   1.348 +void CClientProxy::InternalizeL(RReadStream& aReadStream)
   1.349 +	{
   1.350 +	LOGSTRING("CClientProxy::InternalizeL - start");
   1.351 +
   1.352 +	HBufC* fileName = HBufC::NewL(aReadStream, KMaxFileName);
   1.353 +	delete iFileName;
   1.354 +	iFileName = fileName;
   1.355 +	//
   1.356 +	iPriLink.iPriority = aReadStream.ReadInt32L();
   1.357 +
   1.358 +	const TInt count = aReadStream.ReadInt32L();
   1.359 +	for(TInt i=0; i<count; i++)
   1.360 +		{
   1.361 +		CScheduledTask* task = CScheduledTask::NewLC(aReadStream);
   1.362 +		AddTask(*task);
   1.363 +		CleanupStack::Pop(task);
   1.364 +		}
   1.365 +
   1.366 +	LOGSTRING("CClientProxy::InternalizeL - end");
   1.367 +	}
   1.368 +
   1.369 +void CClientProxy::ExternalizeL(RWriteStream& aWriteStream) const
   1.370 +	{
   1.371 +	LOGSTRING("CClientProxy::ExternalizeL - start");
   1.372 +
   1.373 +	aWriteStream << *iFileName;
   1.374 +	aWriteStream.WriteInt32L(iPriLink.iPriority);
   1.375 +
   1.376 +	TDblQueIter<CScheduledTask> taskIter(const_cast<CClientProxy*>(this)->iTasks);
   1.377 +	taskIter.SetToFirst();
   1.378 +	CScheduledTask* task;
   1.379 +
   1.380 +	// Count tasks
   1.381 +	TInt count = 0;
   1.382 +	while ((task=taskIter++)!=NULL)
   1.383 +		{
   1.384 +		if(task->Persists())
   1.385 +			{	
   1.386 +			count++;
   1.387 +			}
   1.388 +		}
   1.389 +
   1.390 +	// Store leading count
   1.391 +	aWriteStream.WriteInt32L(count);
   1.392 +
   1.393 +	// Store tasks
   1.394 +	taskIter.SetToFirst();
   1.395 +	while ((task=taskIter++)!=NULL)
   1.396 +		{
   1.397 +		if(task->Persists())
   1.398 +		  {
   1.399 +		  aWriteStream << *task;
   1.400 +		  }
   1.401 +		}
   1.402 +
   1.403 +	LOGSTRING("CClientProxy::ExternalizeL - end");
   1.404 +	}
   1.405 +
   1.406 +
   1.407 +TDblQueIter<CScheduledTask> CClientProxy::TaskIterator()
   1.408 +	{
   1.409 +	return TDblQueIter<CScheduledTask>(iTasks);
   1.410 +	}
   1.411 +
   1.412 +
   1.413 +