--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfile/sf_plugin_man.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,755 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// f32\sfile\sf_plugin.cpp
+//
+//
+
+#include <e32std.h>
+#include "sf_std.h"
+#include "sf_plugin_priv.h"
+
+CFsObjectCon* FsPluginManager::iPluginFactories = NULL;
+CFsObjectCon* FsPluginManager::iPluginConns = NULL;
+RFastLock FsPluginManager::iChainLock;
+RPointerArray<CFsPlugin> FsPluginManager::iPluginChain;
+CFsSyncMessageScheduler* FsPluginManager::iScheduler = NULL;
+
+TBool IsPagableDrive(TInt aDrive)
+ {
+ if(LocalDrives::IsValidDriveMapping(aDrive))
+ {
+ TLocalDriveCapsBuf capsBuf;
+ if(!LocalDrives::IsProxyDrive(aDrive) && LocalDrives::GetLocalDrive(aDrive).Caps(capsBuf) && capsBuf().iDriveAtt & KDriveAttPageable)
+ {
+ return (TBool)ETrue;
+ }
+ }
+ return (TBool) EFalse;
+ }
+
+/*
+@param aNonPagableDriveMask - a drive mask of the drives a plugin wishes to mount on
+@return A drive mask of the drives a plugin wishes to mount on not containing any pagable drives.
+*/
+TInt NonPagableDrivesMask(TInt aNonPagableDriveMask)
+ {
+ TInt driveMask = aNonPagableDriveMask;
+ for(TInt i = 0; i < KMaxDrives; i++)
+ {
+ //If we're interested in this drive
+ if((aNonPagableDriveMask & 1<<i) && IsPagableDrive(i))
+ {
+ driveMask ^= 1<<i; //remove this drive
+ }
+ }
+ return driveMask;
+ }
+
+TInt FsPluginManager::UpdateMountedDrive(CFsPlugin* aPlugin, CFsPluginFactory* aFactory,TInt aDrive)
+ {
+ if(aDrive==KPluginAutoAttach) //KPluginAutoAttach
+ {
+ if(!(aFactory->SupportedDrives()&KPluginVersionTwo))
+ { //Version 1 Plugin - Mount on all (except Z and pagble drives)
+ TInt drivesAToY = (KPluginSupportAllDrives>>1);
+ aPlugin->iMountedOn = NonPagableDrivesMask(drivesAToY);
+ }
+ else
+ { //Version 2 Plugin - Mount on what the plugin supports (except pagable drives)
+ aPlugin->iMountedOn = NonPagableDrivesMask((aFactory->SupportedDrives()&(~KPluginVersionTwo)));
+ }
+
+ if(!(aPlugin->iMountedOn &(~KPluginVersionTwo)))
+ { //Are we mounted on anything?
+ return KErrNotSupported;
+ }
+ return KErrNone;
+ }
+
+ // DriveZ special handling
+ if(aDrive==KPluginMountDriveZ)
+ aDrive = EDriveZ;
+
+ //Mounting on a single drive
+ if(!IsPagableDrive(aDrive))
+ {
+ aPlugin->iMountedOn |= 1<<aDrive;
+ return KErrNone;
+ }
+
+ return KErrNotSupported;
+ }
+
+/**
+FsPluginManager::Initialise
+*/
+void FsPluginManager::InitialiseL()
+ {
+ iPluginFactories = TheContainer->CreateL();
+ iPluginConns = TheContainer->CreateL();
+ iPluginChain.Reset();
+ User::LeaveIfError(iChainLock.CreateLocal());
+
+ // Create and install the synchronous message scheduler
+ // - Messages are dispatched here from plugin threads if they are
+ // to be executed in the context of the main file server thread.
+ iScheduler = CFsSyncMessageScheduler::NewL();
+ iScheduler->RunL();
+ }
+
+/**
+FsPluginManager::MountPlugin
+*/
+TInt FsPluginManager::MountPlugin(CFsPluginFactory& aPluginFactory, TInt aDrive, TInt aPos)
+ {
+ TInt uniquePosition = aPluginFactory.UniquePosition();
+ CFsPlugin* pP = NULL;
+ CFsPluginFactory* pF = &aPluginFactory;
+
+ //Version1 plugins could either been mounted on 1 or all drives.
+ //This isn't particularily desirable.
+ // Thus -
+ //For version2 plugins:
+ //Check whether this plugin has already been mounted
+ pP = FindByUniquePosition(uniquePosition);
+ if(pP && (aPluginFactory.iSupportedDrives&KPluginVersionTwo))
+ {
+ //if this plugin has already been mounted then
+ //Instead of trying to mount and failing with KErrInUse,
+ //lets update the iMountedOn instead.
+ return UpdateMountedDrive(pP,pF,aDrive);
+ }
+
+
+ TRAPD(err, pP = aPluginFactory.NewPluginL());
+ if(err != KErrNone)
+ {
+ if(pP)
+ pP->Close();
+ return err;
+ }
+
+ TFullName name = aPluginFactory.Name();
+ pP->SetName(&name);
+ pP->iUniquePos=aPluginFactory.UniquePosition();
+ pP->SetDrive(aDrive);
+
+ //Set which drive(s?) this plugin is mounted on.
+ err = UpdateMountedDrive(pP,pF,aDrive);
+ if(err != KErrNone)
+ {
+ pP->Close();
+ return err;
+ }
+
+ LockChain();
+ err = InsertInPluginStack(pP,aPos);
+ UnlockChain();
+ if(err != KErrNone)
+ {
+ pP->Close();
+ return err;
+ }
+
+ err = InitPlugin(*pP);
+ if(err != KErrNone)
+ {
+ pP->Close();
+ return err;
+ }
+ aPluginFactory.IncrementMounted();
+
+ return KErrNone;
+ }
+
+/**
+Dismounts a plugin
+Must be called with the plugin chain locked.
+*/
+void FsPluginManager::DismountPlugin(CFsPluginFactory& aPluginFactory,TInt aPos)
+ {
+ CFsPlugin* plugin=iPluginChain[aPos];
+
+ if (plugin != NULL)
+ {
+ // Check if there is any requests for this plugin
+ // if so, deliver them to the next supporting plugin
+ TransferRequests(plugin->iThreadP);
+
+ plugin->iThreadP=NULL;
+
+ iPluginChain.Remove(aPos);
+ iPluginChain.Compress();
+
+ //Need this to remove it from container
+ //plugin->Close() deletes plugin.
+ plugin->Close();
+ plugin=NULL;
+ }
+ else
+ {
+ ASSERT(0); // force panic in debug mode
+ }
+
+ aPluginFactory.DecrementMounted();
+ }
+
+/*
+ * This will iterate through a plugins request queue and
+ * search for the first occurance it finds of a CancelPluginOp
+ * request.
+ */
+void FsPluginManager::GetNextCancelPluginOpRequest(CPluginThread* aPluginThread, CFsRequest*& aCancelPluginRequest)
+ {
+ __THRD_PRINT(_L("FsPluginManager::GetNextCancelPluginOpRequest"));
+
+ TDblQueIter<CFsRequest> iter(aPluginThread->iList);
+ CFsRequest* request = NULL;
+
+ while((request=iter++)!=NULL)
+ {
+ if(request->Operation()->iFunction == KCancelPlugin)
+ {
+ aCancelPluginRequest = request;
+ break;
+ }
+ }
+ }
+
+
+
+
+
+/**
+Transfer any outstanding requests to next/previous plugin depending on
+if it is post filter or not
+*/
+void FsPluginManager::TransferRequests(CPluginThread* aPluginThread)
+ {
+ aPluginThread->iListLock.Wait();
+
+ __THRD_PRINT(_L("FsPluginManager::TransferRequests - moving requests"));
+
+ /*
+ * We are transferring requests up and down the chain
+ * because this plugin is being removed.
+ *
+ * There is a potential problem when one of the outstanding requests
+ * is CancelPluginOp which is called when the Session is being closed.
+ * The CancelPluginOp will try to cancel all of the requests on a plugin's
+ * queue which is associated with that session.
+ * DismountPlugin(and thus TransferRequests) is trying to preserve the requests
+ * by passing them along to the Next/Previous plugins.
+ *
+ * If there is a cancel in the chain we must NOT pass any requests to Previous Plugins
+ * as these have already had their chains emptied.
+ * We should also be wary of passing requests up the chain as they will simply be cancelled
+ * somewhere closer to the drive [thread].
+ *
+ * Therefore, we shall check whether there is a KCancelPlugin op in the
+ * chain first.
+ * If there is a cancelPluginOp in the chain, we will cancel of the requests
+ * that are associated with that session.
+ *
+ * After that is out of the way we preserve the remaining requests for different sessions by
+ * passing them on.
+ */
+ if(!aPluginThread->iList.IsEmpty())
+ {
+ CFsRequest* cancelRequest = NULL;
+ //For every CancelPluginOp
+ while(FsPluginManager::GetNextCancelPluginOpRequest(aPluginThread, cancelRequest), cancelRequest!=NULL)
+ {
+ RDebug::Print(_L("Transferring Plugin Requests - CancelPluginOp"));
+ TDblQueIter<CFsRequest> iter(aPluginThread->iList);
+ CFsRequest* request = NULL;
+ //For every request
+ while((request=iter++)!=NULL)
+ {
+ if(request->Session() == cancelRequest->Session() && request != cancelRequest)
+ {
+ request->iLink.Deque();
+ request->Complete(KErrCancel);
+ }
+ }
+ cancelRequest->iLink.Deque();
+ cancelRequest->Complete(KErrNone);
+ cancelRequest = NULL;
+ }
+
+ /*
+ * Now that all requests that were to be cancelled have been cancelled,
+ * we can now go about moving the remaining ones on to , or back to,
+ * the appropriate next or previous plugins.
+ *
+ * ToDo: This next 'while' might be able to be replaced with a call to
+ * DispatchToPlugin/DispatchToDrive instead.
+ */
+ while(!aPluginThread->iList.IsEmpty())
+ {
+ CFsRequest* pR=aPluginThread->iList.First();
+ CFsMessageRequest& mR = *(CFsMessageRequest*) pR;
+ pR->iLink.Deque();
+ pR->iCurrentPlugin=NULL;
+
+ if(pR->IsPluginSpecific())
+ {
+ pR->Complete(KErrCancel);
+ continue;
+ }
+
+ if(pR->IsPostOperation())
+ {
+ //[set the plugin to] pass the request backwards in the chain
+ PrevPlugin(pR->iCurrentPlugin, &mR, EFalse);
+ }
+ else //IsPreOperations
+ {
+ //[set the plugin to] pass the request forwards in the chain
+ NextPlugin(pR->iCurrentPlugin, &mR, EFalse);
+ }
+
+ if(pR->iCurrentPlugin)
+ {
+ pR->iCurrentPlugin->iThreadP->DeliverBack(pR);
+ }
+ else
+ {
+ if(!pR->IsPostOperation() && (pR->DriveNumber()>=EDriveA && pR->DriveNumber()<=EDriveZ))
+ {
+ //Deliver to drive thread
+ CDriveThread* dT=NULL;
+ TInt r=FsThreadManager::GetDriveThread(pR->DriveNumber(),&dT);
+ __ASSERT_ALWAYS(r==KErrNone && dT,Fault(EFsDriveThreadError));
+ CRequestThread* pT = (CRequestThread*)dT;
+ pT->DeliverBack(pR);
+ }
+ else
+ {
+ pR->Complete(KErrCancel);
+ }
+ }
+ }
+ }
+
+ aPluginThread->iExit = ETrue;
+ aPluginThread->iListLock.Signal();
+
+ __THRD_PRINT(_L("FsPluginManager::TransferRequests - all requests moved/cancelled"));
+ }
+
+/**
+Install a plugin factory
+*/
+TInt FsPluginManager::InstallPluginFactory(CFsPluginFactory* aFactory,RLibrary aLib)
+ {
+ TInt r=aFactory->Install();
+ __PRINT1TEMP(_L("InstallPluginFactory %S"),aFactory->Name());
+ if (r==KErrNone)
+ {TRAP(r,iPluginFactories->AddL(aFactory,ETrue))}
+ if (r!=KErrNone)
+ aFactory->Remove();
+ if (r==KErrNone)
+ aFactory->SetLibrary(aLib);
+ else
+ aFactory->Close();
+ return(r);
+ }
+
+/**
+Find a plugin factory by name
+*/
+CFsPluginFactory* FsPluginManager::GetPluginFactory(const TDesC& aName)
+ {
+
+ TInt h=0;
+ TInt r=iPluginFactories->FindByName(h,aName);
+ if (r!=KErrNone)
+ return(NULL);
+ return((CFsPluginFactory*)iPluginFactories->At(h));
+ }
+
+/**
+Find the next plugin that supports the operation
+@param aCheckCurrentOperation - Optional, if false, will return the next plugin,
+ whether the plugin is currently registered
+ for the current function of not. (so long as mounted on the current drive)
+*/
+TInt FsPluginManager::NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest,TBool aLock, TBool aCheckCurrentOperation)
+ {
+ if(aMsgRequest->DirectToDrive())
+ {
+ aPlugin = NULL;
+ return KErrNotFound;
+ }
+
+ TInt r = KErrNone;
+ TInt start;
+ TInt function = aMsgRequest->Operation()->Function();
+ TInt drive = aMsgRequest->DriveNumber();
+
+ if(aLock)
+ LockChain();
+
+ TInt count = iPluginChain.Count();
+
+ if(aPlugin == NULL)
+ start=0;
+ else
+ start = iPluginChain.Find(aPlugin)+1;
+
+ if(start!=KErrNotFound)
+ {
+ for(TInt i=start;i<count;i++)
+ {
+ if(!aCheckCurrentOperation || iPluginChain[i]->IsRegistered(function, CFsPlugin::EPreIntercept))
+ {
+ if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive)))
+ {
+
+ aPlugin = iPluginChain[i];
+ if(aLock)
+ UnlockChain();
+ return(r);
+ }
+ }
+ }
+ }
+ aPlugin = NULL;
+ if(aLock)
+ UnlockChain();
+ return(KErrNotFound);
+ }
+
+/**
+Find the next plugin that supports the operation
+*/
+TInt FsPluginManager::PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock)
+ {
+ if(aMsgRequest->DirectToDrive() && (aMsgRequest->CurrentOperationPtr() != NULL))
+ {
+ aPlugin = NULL;
+ return KErrNotFound;
+ }
+
+ TInt r = KErrNone;
+ TInt start;
+ TInt function = aMsgRequest->Operation()->Function();
+ TInt drive = aMsgRequest->DriveNumber();
+
+ if(aLock)
+ LockChain();
+
+ TInt count= iPluginChain.Count();
+
+ if(aPlugin == NULL)
+ start = count-1;
+ else
+ start = iPluginChain.Find(aPlugin)-1;
+
+ if(start!=KErrNotFound)
+ {
+ for(TInt i=start;i>=0;i--)
+ {
+ CFsPlugin* owner = aMsgRequest->iOwnerPlugin;
+ if(owner == iPluginChain[i])
+ break;
+
+ if(iPluginChain[i]->IsRegistered(function, CFsPlugin::EPostIntercept))
+ {
+ if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive)))
+ {
+
+ aPlugin = iPluginChain[i];
+ if(aLock)
+ UnlockChain();
+ return(r);
+ }
+ }
+ }
+ }
+ aPlugin = NULL;
+ if(aLock)
+ UnlockChain();
+ return(KErrNotFound);
+ }
+/**
+Inserts the plugin in the stack (chain)
+
+if aPos absolute postion, it simply inserts it
+if aPos unique position, it walks through chain and checks the unique positions
+*/
+TInt FsPluginManager::InsertInPluginStack(CFsPlugin*& aPlugin,TInt aPos)
+ {
+ TInt ret=KErrNone;
+ TInt count= iPluginChain.Count();
+ if(aPos == KPluginAutoLocate)
+ {
+ TInt uPos= aPlugin->iUniquePos;
+ for(TInt i=0;i<count;i++)
+ {
+ if(uPos == iPluginChain[i]->iUniquePos)
+ {
+ return KErrInUse;
+ }
+
+ if(uPos < iPluginChain[i]->iUniquePos)
+ {
+ ret=iPluginChain.Insert(aPlugin,i);
+ return ret;
+ }
+ }
+ ret=iPluginChain.Append(aPlugin);
+ }
+ else
+ {
+ // Absolute position
+
+ if(aPos > count)
+ return(KErrNotFound);
+ if(aPos == count)
+ {
+ ret=iPluginChain.Append(aPlugin);
+ return ret;
+ }
+ ret=iPluginChain.Insert(aPlugin,aPos);
+ }
+ return ret;
+ }
+
+/**
+Looks for a plugin in the chain
+*/
+TInt FsPluginManager::IsInChain(TInt aUPos,TInt aPos, TInt aDrive, CFsPluginFactory* aPluginFactory)
+ {
+ TInt count= iPluginChain.Count();
+
+ if(aPos == KPluginAutoLocate)
+ {
+ for(TInt i=0;i<count;i++)
+ {
+ CFsPlugin* pP = iPluginChain[i];
+ if(aPluginFactory->SupportedDrives()&KPluginVersionTwo) //Version2
+ {
+ //If KPluginAutoAttach, then we're dismounted from all drives.
+ //If KPluginMountDriveZ, then check against 25 explicitly (cannot change aDrive:=Z as that==KPluginAutoAttach))
+ //If any other drive mounted.
+ if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || (aDrive==KPluginMountDriveZ && pP->iMountedOn & (1<<EDriveZ)) || pP->iMountedOn & (1<<aDrive)))
+ return i;
+ }
+ else //version1
+ {
+ if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || pP->iMountedOn & (1<<aDrive)))
+ return i;
+ }
+ }
+ return KErrNotFound;
+ }
+
+ if(aPos+1>iPluginChain.Count())
+ return(KErrNotFound);
+
+ if(iPluginChain[aPos]->iUniquePos == aUPos && aDrive==iPluginChain[aPos]->Drive())
+ return aPos;
+ return KErrNotFound;
+ }
+
+/**
+Finds a plugin by unique position
+*/
+CFsPlugin* FsPluginManager::FindByUniquePosition(TInt aUniquePosition)
+ {
+ LockChain();
+ CFsPlugin* plugin = NULL;
+ TInt count= iPluginChain.Count();
+ for(TInt i=0;i<count;i++)
+ {
+ if(aUniquePosition == iPluginChain[i]->iUniquePos)
+ {
+ plugin = iPluginChain[i];
+ break;
+ }
+ }
+ UnlockChain();
+ return plugin;
+ }
+
+/**
+Create a connection to a plugin
+*/
+CFsPluginConn* FsPluginManager::CreatePluginConnL(TInt aUniquePosition, TUint aClientId)
+ {
+ CFsPlugin* pP = FindByUniquePosition(aUniquePosition);
+ if(pP != NULL)
+ {
+ CFsPluginConn* pC = pP->NewPluginConnL();
+ pC->iPluginP = pP;
+ pC->iClientId = aClientId;
+ iPluginConns->AddL(pC, ETrue);
+ return pC;
+ }
+
+ User::Leave(KErrNotFound);
+ return NULL;
+ }
+
+/**
+Create a plugin thread
+Should only by called from main file server thread with plugin thread unavailable
+*/
+TInt FsPluginManager::InitPlugin(CFsPlugin& aPlugin)
+ {
+ TInt err = KErrNone;
+
+ if(!aPlugin.iThreadP)
+ {
+ TRAP(err,aPlugin.iThreadP=CPluginThread::NewL(aPlugin));
+ if(err!=KErrNone)
+ return err;
+ }
+
+ aPlugin.iThreadId = aPlugin.iThreadP->StartL();
+ return err;
+ }
+/**
+Cancels plugin requests
+*/
+void FsPluginManager::CancelPlugin(CFsPlugin* aPlugin,CSessionFs* aSession)
+ {
+ aPlugin->iThreadP->CompleteSessionRequests(aSession,KErrCancel);
+ }
+
+/**
+Gets number of plugins in the plugin stack
+*/
+TInt FsPluginManager::ChainCount()
+ {
+ return(iPluginChain.Count());
+ }
+
+/**
+ * Returns a CFsPlugin* from aPos in the plugin chain.
+ *
+ * To be called whilst already holding the iChainLock.
+ *
+ * @returns (via parameter) CFsPlugin*& aPlugin
+*/
+TInt FsPluginManager::Plugin(CFsPlugin*& aPlugin, TInt aPos)
+ {
+ if(aPos >= iPluginChain.Count() || aPos < 0)
+ return KErrNotFound;
+
+ aPlugin = iPluginChain[aPos];
+ return KErrNone;
+ }
+
+/**
+Locks the chain
+*/
+void FsPluginManager::LockChain()
+ {
+ iChainLock.Wait();
+ }
+
+/**
+Unlocks the chain
+*/
+void FsPluginManager::UnlockChain()
+ {
+ iChainLock.Signal();
+ }
+
+/**
+Gets plugin conn from handle
+*/
+CFsPluginConn* FsPluginManager::GetPluginConnFromHandle(CSessionFs* aSession, TInt aHandle)
+ {
+ return((CFsPluginConn*)(SessionObjectFromHandle(aHandle,iPluginConns->UniqueID(),aSession)));
+ }
+
+/**
+Checks if the current thread is plugin conn's thread
+*/
+TBool FsPluginManager::IsPluginConnThread(TThreadId tid, CFsPlugin* aPlugin)
+ {
+ iPluginConns->Lock();
+ TInt count = iPluginConns->Count();
+ while(count--)
+ {
+ CFsPluginConn* conn = (CFsPluginConn*)(*iPluginConns)[count];
+ if(conn->Plugin() == aPlugin)
+ {
+ if(conn->ClientId() == tid)
+ {
+ iPluginConns->Unlock();
+ return ETrue;
+ }
+ }
+ }
+ iPluginConns->Unlock();
+ return EFalse;
+ }
+
+/**
+Dispatch a synchronous message
+*/
+void FsPluginManager::DispatchSync(CFsRequest* aRequest)
+ {
+ __THRD_PRINT(_L("FsPluginManager::DispatchSync"));
+ if(!FsThreadManager::IsMainThread() && iScheduler)
+ {
+ iScheduler->Dispatch(aRequest);
+ }
+ else
+ {
+ aRequest->Process();
+ }
+ }
+
+void FsPluginManager::CompleteSessionRequests(CSessionFs* aSession, TInt aValue, CFsInternalRequest* aRequest)
+/**
+Complete outstanding requests for the specified session
+*/
+ {
+ __PRINT2(_L("FsPluginManager::CompleteSessionRequests(%08x, %d)"), aSession, aValue);
+
+ // Iterate through all plugins, cancelling outstanding session requests
+ aRequest->Set(CancelPluginOp, aSession);
+
+ FsPluginManager::LockChain();
+ TInt count = FsPluginManager::ChainCount();
+ TInt i;
+ for(i=0; i<count; i++)
+ {
+ CFsPlugin* plugin = NULL;
+ User::LeaveIfError(FsPluginManager::Plugin(plugin, i));
+ __ASSERT_DEBUG(plugin, User::Leave(KErrNotFound));
+ aRequest->iCurrentPlugin = plugin;
+ aRequest->Status() = KRequestPending;
+ aRequest->Dispatch();
+ //Cancel is delivered to the front of the request queue
+ //so hopefully this wont take too long.
+ FsPluginManager::UnlockChain();
+ User::WaitForRequest(aRequest->Status());
+ FsPluginManager::LockChain();
+ __ASSERT_ALWAYS(aRequest->Status().Int()==KErrNone||aRequest->Status().Int()==KErrCancel,Fault(ESessionDisconnectThread2));
+ count = FsPluginManager::ChainCount();
+ }
+ FsPluginManager::UnlockChain();
+
+// RDebug::Print(_L("FsPluginManager::CompleteSessionRequests - CSRs"));
+ iScheduler->CompleteSessionRequests(aSession, aValue);
+ }
+
+