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 +