diff -r 000000000000 -r e4d67989cc36 genericservices/taskscheduler/SCHSVR/SCHCLI.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericservices/taskscheduler/SCHSVR/SCHCLI.CPP Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,410 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +// System includes +#include +#include +#include + + +// User includes +#include "SCHCLI.H" +#include "SchLogger.h" +#include "SCHEXEC.H" +#include "SCHLOG.h" + + +// Constants +#define KEllipsis 0x2026 +const TInt KTaskArrayGranularity = 1; +_LIT(KTaskNameSeparator, ", "); + + + +// +// CClientProxy +// +CClientProxy::CClientProxy(RFs& aFsSession, CSchLogManager& aLogManager) +: iFsSession(aFsSession), + iTasks(CScheduledTask::Offset()), + iSchLogManager(aLogManager) + { + } + +CClientProxy::CClientProxy(RFs& aFsSession, TInt aPriority, CSchLogManager& aLogManager) +: iFsSession(aFsSession), + iTasks(CScheduledTask::Offset()), + iSchLogManager(aLogManager) + { + iPriLink.iPriority = aPriority; + } + +CClientProxy::~CClientProxy() + { + LOGSTRING("CClientProxy::~CClientProxy - start"); + + TDblQueIter taskIter(iTasks); + taskIter.SetToFirst(); + CScheduledTask* task; + while ((task = taskIter++) != NULL) + { + RemoveTask(task); + } + delete iFileName; + LOGSTRING("CClientProxy::~CClientProxy - end"); + } + +void CClientProxy::ConstructL(const TDesC& aFileName) + { + iFileName = aFileName.AllocL(); + } + +CClientProxy* CClientProxy::NewL(RFs& aFsSession, + const TDesC& aFileName, + TInt aPriority, + CSchLogManager& aLogManager) + { + CClientProxy* self = new(ELeave) CClientProxy(aFsSession, aPriority,aLogManager); + CleanupStack::PushL(self); + self->ConstructL(aFileName); + CleanupStack::Pop(); + return self; + } + +CClientProxy* CClientProxy::NewL(RFs& aFsSession, + RReadStream& aStream, + CSchLogManager& aLogManager) + { + CClientProxy* self = new(ELeave) CClientProxy(aFsSession,aLogManager); + CleanupStack::PushL(self); + aStream >> *self; + CleanupStack::Pop(); + return self; + } + +TBool CClientProxy::IsEqual(const TDesC& aFilename, TInt aPriority) const + { + // Equality here means: same DLL filename, DLL ordinal & priority + return ((*iFileName == aFilename) && (iPriLink.iPriority == aPriority)); + } + +void CClientProxy::AddTask(CScheduledTask& aTask) + { + LOGSTRING("CClientProxy::AddTask - start"); + iTasks.Add(aTask); + iUsers++; + LOGSTRING("CClientProxy::AddTask - end"); + } + +void CClientProxy::RemoveTask(CScheduledTask* aTask) + { + LOGSTRING("CClientProxy::RemoveTask - start"); + iUsers--; + aTask->Remove(); + delete aTask; + LOGSTRING("CClientProxy::RemoveTask - end"); + } + +// +static void BuildTaskErrorMessage(const CArrayPtr& aTasks, TDes& aErrorMessage) +// +// Establish the names of all the tasks that potentially might fail +// when executing the task. This is done *before* actually executing the +// tasks as its not possible to discern (at failure time) which tasks +// were actually executing (because we don't know at what time the task +// executor was spawned). +// + { + const TInt count = aTasks.Count(); + for(TInt i=0; iInfo().iName; + if (aErrorMessage.Length() + taskName.Length() > KLogMaxSubjectLength - KTaskNameSeparator().Length()) + { + // The task name that still needs adding to the subject line (of the + // log entry) is too big to fit within KLogCallEventTypeUid characters. + // Trim the task name so that it will fit, and append the ellipsis + // character to indicate that more tasks were present but unable to be + // shown. + TInt lengthOfTaskNameToAccept = (KLogMaxSubjectLength - aErrorMessage.Length()) - KTaskNameSeparator().Length(); + if (lengthOfTaskNameToAccept <= 0) + break; + aErrorMessage += taskName.Left(lengthOfTaskNameToAccept); + aErrorMessage.Append(KEllipsis); + + // Exit the 'for' loop as there isn't any more room to hold subsequent + // tasks that potentially failed... + break; + } + else + { + aErrorMessage += taskName; + } + + if (i* tasks = NULL; + TRAPD(err, tasks = DueTasksL()); + if(err) + { + iSchLogManager.LogError(err); + return; + } + + // Create the task error message, just in case an error occurs + TBuf errorMessage; + BuildTaskErrorMessage(*tasks, errorMessage); + + TInt error =DoExecuteTasks(*tasks, errorMessage); + if(error) + iSchLogManager.LogError(errorMessage,error); + delete tasks; + } + +TInt CClientProxy::DoExecuteTasks(const CArrayPtr& aTasks, + const TDesC& aErrorMessage) + { + // Generate a unique task name + TTime timenow; + timenow.UniversalTime(); + TBuf<24> filename; // 20 is the longest decimal char length of a 64-bit number + 4 for extension + filename.Format(_L("%Ld.tmp"),timenow.Int64()); + + // Save & perform execution + TRAPD(error, DoExecuteTasksL(aTasks, filename, aErrorMessage)); + + if (error != KErrNone) + { + LOGSTRING2("CClientProxy::ExecuteTasksL - attempted to execute tasks, error was %d", error); + // Cleanup the file that was created if the execution fails in any way. Note + // that it might not have been created + + // If a debug build - record error + TInt fileDeleteErr=iFsSession.Delete(filename); + if (fileDeleteErr != KErrNone) + { + LOGSTRING2("CClientProxy::DoExecuteTasks - Failed to delete file. Error = %d", fileDeleteErr); + } + } + return error; + } + +void CClientProxy::DoExecuteTasksL(const CArrayPtr& aTasks, + const TDesC& aFileName, + const TDesC& aErrorMessage) + { + // Save the tasks to disk + SaveTasksToFileL(aTasks, aFileName); + + // Spawn the task executor active object (deletes itself upon completion) + CTaskExecutor* executor = CTaskExecutor::NewLC(aErrorMessage,aFileName,*iFileName,iSchLogManager); + executor->ExecuteL(); + CleanupStack::Pop(executor); + // Don't delete executor here as it does it itself once + // the task has finished (delete this in its RunL() ) + } + + +CArrayPtr* CClientProxy::DueTasksL() +// +// Returns a copy of any due tasks +// + { + CArrayPtrFlat* tasks = new(ELeave)CArrayPtrFlat (KTaskArrayGranularity); + CleanupStack::PushL(tasks); + TDblQueIter taskIter(iTasks); + taskIter.SetToFirst(); + CScheduledTask* task; + while ((task=taskIter++)!=NULL) + { + if (task->Due()) + { + tasks->AppendL(task); + } + } + CleanupStack::Pop(tasks); + return tasks; + } + + +CFileStore* CClientProxy::CreateStoreL(const TDesC& aName,TUint aFileMode) +// +// To make the code clearer - called within a trap frame that shouldn't leave anything +// on cleanup stack. +// + { + CFileStore* store = CDirectFileStore::CreateLC(iFsSession, aName, aFileMode); + CleanupStack::Pop(store); + return store; + } + +void CClientProxy::SaveTasksToFileL(const CArrayPtr& aTasks, const TDesC& aFileName) + { + LOGSTRING("CClientProxy::SaveTasksToFileL - start"); + + // Create the file store + LOGSTRING("CClientProxy::SaveTasksToFileL - creating store"); + CFileStore* store = CreateStoreL(aFileName, EFileWrite); + CleanupStack::PushL(store); + + // Save the actual tasks to the store + LOGSTRING("CClientProxy::SaveTasksToFileL - saving tasks"); + SaveTasksL(*store, aTasks); + CleanupStack::PopAndDestroy(store); + + LOGSTRING("CClientProxy::SaveTasksToFileL - end"); + } + +void CClientProxy::SaveTasksL(CFileStore& aStore, const CArrayPtr& aTasks) + { + LOGSTRING("CClientProxy::SaveTasksL - start"); + aStore.SetTypeL(KDirectFileStoreLayoutUid); + + // Save the tasks + RStoreWriteStream outstream; + TStreamId id = outstream.CreateLC(aStore); + const TInt count = aTasks.Count(); + LOGSTRING2("CClientProxy::SaveTasksL - saving %d tasks", count); + outstream.WriteInt32L(count); + for (TInt i=0;iExternalizeL(outstream); + } + outstream.CommitL(); + CleanupStack::PopAndDestroy(); // outstream + + aStore.SetRootL(id); + aStore.CommitL(); + LOGSTRING("CClientProxy::SaveTasksL - end"); + } + +void CClientProxy::RemoveDueTasks() + { + LOGSTRING("CClientProxy::RemoveDueTasks - start"); + + TDblQueIter taskIter(iTasks); + taskIter.SetToFirst(); + CScheduledTask* task; + // + while ((task=taskIter++)!=NULL) + { + if (task->Due()) + { + LOGSTRING3("CClientProxy::RemoveDueTasks - found due task %S, %d", &task->Info().iName, task->Info().iTaskId); + + if (!task->Info().iRepeat) + { + LOGSTRING("CClientProxy::RemoveDueTasks - task has no repeats left - it's being removed"); + RemoveTask(task); + } + else + { + LOGSTRING("CClientProxy::RemoveDueTasks - task still has some repeats, setting as 'no longer due'"); + task->SetDue(EFalse); + } + } + } + iReadyToExecute = EFalse; + LOGSTRING("CClientProxy::RemoveDueTasks - end"); + } + +void CClientProxy::TransferTasks(CClientProxy& aTargetClient) + { + TDblQueIter taskIter(iTasks); + taskIter.SetToFirst(); + CScheduledTask* task; + while ((task=taskIter++)!=NULL) + { + task->Remove(); + aTargetClient.AddTask(*task); + } + } + +void CClientProxy::InternalizeL(RReadStream& aReadStream) + { + LOGSTRING("CClientProxy::InternalizeL - start"); + + HBufC* fileName = HBufC::NewL(aReadStream, KMaxFileName); + delete iFileName; + iFileName = fileName; + // + iPriLink.iPriority = aReadStream.ReadInt32L(); + + const TInt count = aReadStream.ReadInt32L(); + for(TInt i=0; i taskIter(const_cast(this)->iTasks); + taskIter.SetToFirst(); + CScheduledTask* task; + + // Count tasks + TInt count = 0; + while ((task=taskIter++)!=NULL) + { + if(task->Persists()) + { + count++; + } + } + + // Store leading count + aWriteStream.WriteInt32L(count); + + // Store tasks + taskIter.SetToFirst(); + while ((task=taskIter++)!=NULL) + { + if(task->Persists()) + { + aWriteStream << *task; + } + } + + LOGSTRING("CClientProxy::ExternalizeL - end"); + } + + +TDblQueIter CClientProxy::TaskIterator() + { + return TDblQueIter(iTasks); + } + + +