--- /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 <logwraplimits.h>
+#include <logwrap.h>
+#include <schtask.h>
+
+
+// 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<CScheduledTask> 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<CScheduledTask>& 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; i<count; i++)
+ {
+ const TDesC& taskName = aTasks.At(i)->Info().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<count-1) // not the last taskName
+ {
+ // Append a comma
+ aErrorMessage += KTaskNameSeparator;
+ }
+ }
+ }
+
+void CClientProxy::ExecuteTasks()
+ {
+ // generate an array of due tasks
+ CArrayPtr<CScheduledTask>* tasks = NULL;
+ TRAPD(err, tasks = DueTasksL());
+ if(err)
+ {
+ iSchLogManager.LogError(err);
+ return;
+ }
+
+ // Create the task error message, just in case an error occurs
+ TBuf<KLogMaxSubjectLength> errorMessage;
+ BuildTaskErrorMessage(*tasks, errorMessage);
+
+ TInt error =DoExecuteTasks(*tasks, errorMessage);
+ if(error)
+ iSchLogManager.LogError(errorMessage,error);
+ delete tasks;
+ }
+
+TInt CClientProxy::DoExecuteTasks(const CArrayPtr<CScheduledTask>& 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<CScheduledTask>& 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<CScheduledTask>* CClientProxy::DueTasksL()
+//
+// Returns a copy of any due tasks
+//
+ {
+ CArrayPtrFlat<CScheduledTask>* tasks = new(ELeave)CArrayPtrFlat<CScheduledTask> (KTaskArrayGranularity);
+ CleanupStack::PushL(tasks);
+ TDblQueIter<CScheduledTask> 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<CScheduledTask>& 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<CScheduledTask>& 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;i<count;i++)
+ {
+ CScheduledTask* task = aTasks.At(i);
+ task->ExternalizeL(outstream);
+ }
+ outstream.CommitL();
+ CleanupStack::PopAndDestroy(); // outstream
+
+ aStore.SetRootL(id);
+ aStore.CommitL();
+ LOGSTRING("CClientProxy::SaveTasksL - end");
+ }
+
+void CClientProxy::RemoveDueTasks()
+ {
+ LOGSTRING("CClientProxy::RemoveDueTasks - start");
+
+ TDblQueIter<CScheduledTask> 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<CScheduledTask> 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<count; i++)
+ {
+ CScheduledTask* task = CScheduledTask::NewLC(aReadStream);
+ AddTask(*task);
+ CleanupStack::Pop(task);
+ }
+
+ LOGSTRING("CClientProxy::InternalizeL - end");
+ }
+
+void CClientProxy::ExternalizeL(RWriteStream& aWriteStream) const
+ {
+ LOGSTRING("CClientProxy::ExternalizeL - start");
+
+ aWriteStream << *iFileName;
+ aWriteStream.WriteInt32L(iPriLink.iPriority);
+
+ TDblQueIter<CScheduledTask> taskIter(const_cast<CClientProxy*>(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<CScheduledTask> CClientProxy::TaskIterator()
+ {
+ return TDblQueIter<CScheduledTask>(iTasks);
+ }
+
+
+