1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_plugin_man.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,771 @@
1.4 +// Copyright (c) 2005-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 the License "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 +// f32\sfile\sf_plugin.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <e32std.h>
1.22 +#include "sf_std.h"
1.23 +#include "sf_plugin_priv.h"
1.24 +
1.25 +CFsObjectCon* FsPluginManager::iPluginFactories = NULL;
1.26 +CFsObjectCon* FsPluginManager::iPluginConns = NULL;
1.27 +RFastLock FsPluginManager::iChainLock;
1.28 +RPointerArray<CFsPlugin> FsPluginManager::iPluginChain;
1.29 +CFsSyncMessageScheduler* FsPluginManager::iScheduler = NULL;
1.30 +
1.31 +TBool IsPagableDrive(TInt aDrive)
1.32 + {
1.33 + if(LocalDrives::IsValidDriveMapping(aDrive))
1.34 + {
1.35 + TLocalDriveCapsBuf capsBuf;
1.36 + if(!LocalDrives::IsProxyDrive(aDrive) && LocalDrives::GetLocalDrive(aDrive).Caps(capsBuf) && capsBuf().iDriveAtt & KDriveAttPageable)
1.37 + {
1.38 + return (TBool)ETrue;
1.39 + }
1.40 + }
1.41 + return (TBool) EFalse;
1.42 + }
1.43 +
1.44 +/*
1.45 +@param aNonPagableDriveMask - a drive mask of the drives a plugin wishes to mount on
1.46 +@return A drive mask of the drives a plugin wishes to mount on not containing any pagable drives.
1.47 +*/
1.48 +TInt NonPagableDrivesMask(TInt aNonPagableDriveMask)
1.49 + {
1.50 + TInt driveMask = aNonPagableDriveMask;
1.51 + for(TInt i = 0; i < KMaxDrives; i++)
1.52 + {
1.53 + //If we're interested in this drive
1.54 + if((aNonPagableDriveMask & 1<<i) && IsPagableDrive(i))
1.55 + {
1.56 + driveMask ^= 1<<i; //remove this drive
1.57 + }
1.58 + }
1.59 + return driveMask;
1.60 + }
1.61 +
1.62 +TInt FsPluginManager::UpdateMountedDrive(CFsPlugin* aPlugin, CFsPluginFactory* aFactory,TInt aDrive)
1.63 + {
1.64 + if(aDrive==KPluginAutoAttach) //KPluginAutoAttach
1.65 + {
1.66 + if(!(aFactory->SupportedDrives()&KPluginVersionTwo))
1.67 + { //Version 1 Plugin - Mount on all (except Z and pagble drives)
1.68 + TInt drivesAToY = (KPluginSupportAllDrives>>1);
1.69 + aPlugin->iMountedOn = NonPagableDrivesMask(drivesAToY);
1.70 + }
1.71 + else
1.72 + { //Version 2 Plugin - Mount on what the plugin supports (except pagable drives)
1.73 + aPlugin->iMountedOn = NonPagableDrivesMask((aFactory->SupportedDrives()&(~KPluginVersionTwo)));
1.74 + }
1.75 +
1.76 + if(!(aPlugin->iMountedOn &(~KPluginVersionTwo)))
1.77 + { //Are we mounted on anything?
1.78 + return KErrNotSupported;
1.79 + }
1.80 + return KErrNone;
1.81 + }
1.82 +
1.83 + // DriveZ special handling
1.84 + if(aDrive==KPluginMountDriveZ)
1.85 + aDrive = EDriveZ;
1.86 +
1.87 + //Mounting on a single drive
1.88 + if(!IsPagableDrive(aDrive))
1.89 + {
1.90 + aPlugin->iMountedOn |= 1<<aDrive;
1.91 + return KErrNone;
1.92 + }
1.93 +
1.94 + return KErrNotSupported;
1.95 + }
1.96 +
1.97 +/**
1.98 +FsPluginManager::Initialise
1.99 +*/
1.100 +void FsPluginManager::InitialiseL()
1.101 + {
1.102 + iPluginFactories = TheContainer->CreateL();
1.103 + iPluginConns = TheContainer->CreateL();
1.104 + iPluginChain.Reset();
1.105 + User::LeaveIfError(iChainLock.CreateLocal());
1.106 +
1.107 + // Create and install the synchronous message scheduler
1.108 + // - Messages are dispatched here from plugin threads if they are
1.109 + // to be executed in the context of the main file server thread.
1.110 + iScheduler = CFsSyncMessageScheduler::NewL();
1.111 + iScheduler->RunL();
1.112 + }
1.113 +
1.114 +/**
1.115 +FsPluginManager::MountPlugin
1.116 +*/
1.117 +TInt FsPluginManager::MountPlugin(CFsPluginFactory& aPluginFactory, TInt aDrive, TInt aPos)
1.118 + {
1.119 + TInt uniquePosition = aPluginFactory.UniquePosition();
1.120 + CFsPlugin* pP = NULL;
1.121 + CFsPluginFactory* pF = &aPluginFactory;
1.122 +
1.123 + //Version1 plugins could either been mounted on 1 or all drives.
1.124 + //This isn't particularily desirable.
1.125 + // Thus -
1.126 + //For version2 plugins:
1.127 + //Check whether this plugin has already been mounted
1.128 + pP = FindByUniquePosition(uniquePosition);
1.129 + if(pP && (aPluginFactory.iSupportedDrives&KPluginVersionTwo))
1.130 + {
1.131 + //if this plugin has already been mounted then
1.132 + //Instead of trying to mount and failing with KErrInUse,
1.133 + //lets update the iMountedOn instead.
1.134 + return UpdateMountedDrive(pP,pF,aDrive);
1.135 + }
1.136 +
1.137 +
1.138 + TRAPD(err, pP = aPluginFactory.NewPluginL());
1.139 + if(err != KErrNone)
1.140 + {
1.141 + if(pP)
1.142 + pP->Close();
1.143 + return err;
1.144 + }
1.145 +
1.146 + TFullName name = aPluginFactory.Name();
1.147 + pP->SetName(&name);
1.148 + pP->iUniquePos=aPluginFactory.UniquePosition();
1.149 + pP->SetDrive(aDrive);
1.150 +
1.151 + //Set which drive(s?) this plugin is mounted on.
1.152 + err = UpdateMountedDrive(pP,pF,aDrive);
1.153 + if(err != KErrNone)
1.154 + {
1.155 + pP->Close();
1.156 + return err;
1.157 + }
1.158 +
1.159 + LockChain();
1.160 + err = InsertInPluginStack(pP,aPos);
1.161 + UnlockChain();
1.162 + if(err != KErrNone)
1.163 + {
1.164 + pP->Close();
1.165 + return err;
1.166 + }
1.167 +
1.168 + err = InitPlugin(*pP);
1.169 + if(err != KErrNone)
1.170 + {
1.171 + return err;
1.172 + }
1.173 + aPluginFactory.IncrementMounted();
1.174 +
1.175 + return KErrNone;
1.176 + }
1.177 +
1.178 +/**
1.179 +Dismounts a plugin
1.180 +
1.181 +Must be called with the plugin chain locked.
1.182 +*/
1.183 +void FsPluginManager::DismountPlugin(CFsPluginFactory& aPluginFactory,TInt aPos)
1.184 + {
1.185 + CFsPlugin* plugin=iPluginChain[aPos];
1.186 +
1.187 + if (plugin != NULL)
1.188 + {
1.189 + // Check if there is any requests for this plugin
1.190 + // if so, deliver them to the next supporting plugin
1.191 + TransferRequests(plugin->iThreadP);
1.192 +
1.193 + plugin->iThreadP=NULL;
1.194 +
1.195 + //Remove the plugin from the chain
1.196 + iPluginChain.Remove(aPos);
1.197 + iPluginChain.Compress();
1.198 +
1.199 + //Close the plugin (destructed when CPluginThread is destructed).
1.200 + plugin->Close();
1.201 + plugin=NULL;
1.202 + }
1.203 + else
1.204 + {
1.205 + ASSERT(0); // force panic in debug mode
1.206 + }
1.207 +
1.208 + aPluginFactory.DecrementMounted();
1.209 + }
1.210 +
1.211 +/*
1.212 + * This will iterate through a plugins request queue and
1.213 + * search for the first occurance it finds of a CancelPluginOp
1.214 + * request.
1.215 + */
1.216 +void FsPluginManager::GetNextCancelPluginOpRequest(CPluginThread* aPluginThread, CFsRequest*& aCancelPluginRequest)
1.217 + {
1.218 + __THRD_PRINT(_L("FsPluginManager::GetNextCancelPluginOpRequest"));
1.219 +
1.220 + TDblQueIter<CFsRequest> iter(aPluginThread->iList);
1.221 + CFsRequest* request = NULL;
1.222 +
1.223 + while((request=iter++)!=NULL)
1.224 + {
1.225 + if(request->Operation()->iFunction == KCancelPlugin)
1.226 + {
1.227 + aCancelPluginRequest = request;
1.228 + break;
1.229 + }
1.230 + }
1.231 + }
1.232 +
1.233 +
1.234 +
1.235 +
1.236 +
1.237 +/**
1.238 +Transfer any outstanding requests to next/previous plugin depending on
1.239 +if it is post filter or not
1.240 +
1.241 +Must be called with the plugin chain locked.
1.242 +Attains plugin-thread's listlock.
1.243 +*/
1.244 +void FsPluginManager::TransferRequests(CPluginThread* aPluginThread)
1.245 + {
1.246 + aPluginThread->iListLock.Wait();
1.247 +
1.248 + __THRD_PRINT(_L("FsPluginManager::TransferRequests - moving requests"));
1.249 +
1.250 + /*
1.251 + * We are transferring requests up and down the chain
1.252 + * because this plugin is being removed.
1.253 + *
1.254 + * There is a potential problem when one of the outstanding requests
1.255 + * is CancelPluginOp which is called when the Session is being closed.
1.256 + * The CancelPluginOp will try to cancel all of the requests on a plugin's
1.257 + * queue which is associated with that session.
1.258 + * DismountPlugin(and thus TransferRequests) is trying to preserve the requests
1.259 + * by passing them along to the Next/Previous plugins.
1.260 + *
1.261 + * If there is a cancel in the chain we must NOT pass any requests to Previous Plugins
1.262 + * as these have already had their chains emptied.
1.263 + * We should also be wary of passing requests up the chain as they will simply be cancelled
1.264 + * somewhere closer to the drive [thread].
1.265 + *
1.266 + * Therefore, we shall check whether there is a KCancelPlugin op in the
1.267 + * chain first.
1.268 + * If there is a cancelPluginOp in the chain, we will cancel of the requests
1.269 + * that are associated with that session.
1.270 + *
1.271 + * After that is out of the way we preserve the remaining requests for different sessions by
1.272 + * passing them on.
1.273 + */
1.274 + if(!aPluginThread->iList.IsEmpty())
1.275 + {
1.276 + CFsRequest* cancelRequest = NULL;
1.277 + //For every CancelPluginOp
1.278 + while(FsPluginManager::GetNextCancelPluginOpRequest(aPluginThread, cancelRequest), cancelRequest!=NULL)
1.279 + {
1.280 + RDebug::Print(_L("Transferring Plugin Requests - CancelPluginOp"));
1.281 + TDblQueIter<CFsRequest> iter(aPluginThread->iList);
1.282 + CFsRequest* request = NULL;
1.283 + //For every request
1.284 + while((request=iter++)!=NULL)
1.285 + {
1.286 + if(request->Session() == cancelRequest->Session() && request != cancelRequest)
1.287 + {
1.288 + request->iLink.Deque();
1.289 + request->Complete(KErrCancel);
1.290 + }
1.291 + }
1.292 + cancelRequest->iLink.Deque();
1.293 + cancelRequest->Complete(KErrNone);
1.294 + cancelRequest = NULL;
1.295 + }
1.296 +
1.297 + /*
1.298 + * Now that all requests that were to be cancelled have been cancelled,
1.299 + * we can now go about moving the remaining ones on to , or back to,
1.300 + * the appropriate next or previous plugins.
1.301 + *
1.302 + * ToDo: This next 'while' might be able to be replaced with a call to
1.303 + * DispatchToPlugin/DispatchToDrive instead.
1.304 + */
1.305 + while(!aPluginThread->iList.IsEmpty())
1.306 + {
1.307 + CFsRequest* pR=aPluginThread->iList.First();
1.308 + CFsMessageRequest& mR = *(CFsMessageRequest*) pR;
1.309 + pR->iLink.Deque();
1.310 + pR->iCurrentPlugin=NULL;
1.311 +
1.312 + if(pR->IsPluginSpecific())
1.313 + {
1.314 + pR->Complete(KErrCancel);
1.315 + continue;
1.316 + }
1.317 +
1.318 + if(pR->IsPostOperation())
1.319 + {
1.320 + //[set the plugin to] pass the request backwards in the chain
1.321 + PrevPlugin(pR->iCurrentPlugin, &mR, EFalse);
1.322 + }
1.323 + else //IsPreOperations
1.324 + {
1.325 + //[set the plugin to] pass the request forwards in the chain
1.326 + NextPlugin(pR->iCurrentPlugin, &mR, EFalse);
1.327 + }
1.328 +
1.329 + if(pR->iCurrentPlugin)
1.330 + {
1.331 + pR->iCurrentPlugin->iThreadP->DeliverBack(pR);
1.332 + }
1.333 + else
1.334 + {
1.335 + if(!pR->IsPostOperation() && (pR->DriveNumber()>=EDriveA && pR->DriveNumber()<=EDriveZ))
1.336 + {
1.337 + //Deliver to drive thread
1.338 + CDriveThread* dT=NULL;
1.339 + TInt r=FsThreadManager::GetDriveThread(pR->DriveNumber(),&dT);
1.340 + __ASSERT_ALWAYS(r==KErrNone && dT,Fault(EFsDriveThreadError));
1.341 + CRequestThread* pT = (CRequestThread*)dT;
1.342 + pT->DeliverBack(pR);
1.343 + }
1.344 + else
1.345 + {
1.346 + pR->Complete(KErrCancel);
1.347 + }
1.348 + }
1.349 + }
1.350 + }
1.351 +
1.352 + aPluginThread->iExit = ETrue;
1.353 + aPluginThread->iListLock.Signal();
1.354 +
1.355 + __THRD_PRINT(_L("FsPluginManager::TransferRequests - all requests moved/cancelled"));
1.356 + }
1.357 +
1.358 +/**
1.359 +Install a plugin factory
1.360 +*/
1.361 +TInt FsPluginManager::InstallPluginFactory(CFsPluginFactory* aFactory,RLibrary aLib)
1.362 + {
1.363 + TInt r=aFactory->Install();
1.364 + __PRINT1TEMP(_L("InstallPluginFactory %S"),aFactory->Name());
1.365 + if (r==KErrNone)
1.366 + {TRAP(r,iPluginFactories->AddL(aFactory,ETrue))}
1.367 + if (r!=KErrNone)
1.368 + aFactory->Remove();
1.369 + if (r==KErrNone)
1.370 + aFactory->SetLibrary(aLib);
1.371 + else
1.372 + aFactory->Close();
1.373 + return(r);
1.374 + }
1.375 +
1.376 +/**
1.377 +Find a plugin factory by name
1.378 +*/
1.379 +CFsPluginFactory* FsPluginManager::GetPluginFactory(const TDesC& aName)
1.380 + {
1.381 +
1.382 + TInt h=0;
1.383 + TInt r=iPluginFactories->FindByName(h,aName);
1.384 + if (r!=KErrNone)
1.385 + return(NULL);
1.386 + return((CFsPluginFactory*)iPluginFactories->At(h));
1.387 + }
1.388 +
1.389 +/**
1.390 +Find the next plugin that supports the operation
1.391 +
1.392 +@param aPlugin - On calling the function this may contain either NULL or the current plugin.
1.393 + If it is called with NULL, then we start to look for plugins from the beginning of the chain.
1.394 + If is is called with a plugin then we start to look after that plugin for the next one.
1.395 + On return, aPlugin shall contain either a plugin or NULL.
1.396 +
1.397 +@param aLock - If this is set to ETRUE, then the function shall lock the plugin chain.
1.398 + If this is set to EFALSE, then the caller of the function MUST already hold the lock.
1.399 +
1.400 +@param aCheckCurrentOperation - Optional, if false, will return the next plugin,
1.401 + whether the plugin is currently registered
1.402 + for the current function or not. (so long as mounted on the current drive)
1.403 +*/
1.404 +TInt FsPluginManager::NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest,TBool aLock, TBool aCheckCurrentOperation)
1.405 + {
1.406 + if(aMsgRequest->DirectToDrive())
1.407 + {
1.408 + aPlugin = NULL;
1.409 + return KErrNotFound;
1.410 + }
1.411 +
1.412 + TInt start;
1.413 + TInt function = aMsgRequest->Operation()->Function();
1.414 + TInt drive = aMsgRequest->DriveNumber();
1.415 +
1.416 + if(aLock)
1.417 + LockChain();
1.418 +
1.419 + //the plugin chain lock must be held by this point.
1.420 + TInt count = iPluginChain.Count();
1.421 +
1.422 + if(aPlugin == NULL)
1.423 + start=0;
1.424 + else
1.425 + start = iPluginChain.Find(aPlugin)+1;
1.426 +
1.427 + if(start!=KErrNotFound)
1.428 + {
1.429 + for(TInt i=start;i<count;i++)
1.430 + {
1.431 + if(!aCheckCurrentOperation || iPluginChain[i]->IsRegistered(function, CFsPlugin::EPreIntercept))
1.432 + {
1.433 + if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive)))
1.434 + {
1.435 +
1.436 + aPlugin = iPluginChain[i];
1.437 + if(aLock)
1.438 + UnlockChain();
1.439 + return KErrNone;
1.440 + }
1.441 + }
1.442 + }
1.443 + }
1.444 + aPlugin = NULL;
1.445 + if(aLock)
1.446 + UnlockChain();
1.447 + return KErrNotFound;
1.448 + }
1.449 +
1.450 +/**
1.451 +Find the next plugin that supports the operation
1.452 +
1.453 +@see FsPluginManager::NextPlugin
1.454 +*/
1.455 +TInt FsPluginManager::PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock)
1.456 + {
1.457 + if(aMsgRequest->DirectToDrive() && (aMsgRequest->CurrentOperationPtr() != NULL))
1.458 + {
1.459 + aPlugin = NULL;
1.460 + return KErrNotFound;
1.461 + }
1.462 +
1.463 + TInt start;
1.464 + TInt function = aMsgRequest->Operation()->Function();
1.465 + TInt drive = aMsgRequest->DriveNumber();
1.466 +
1.467 + if(aLock)
1.468 + LockChain();
1.469 +
1.470 + //the plugin chain lock must be held by this point.
1.471 + TInt count= iPluginChain.Count();
1.472 +
1.473 + if(aPlugin == NULL)
1.474 + start = count-1;
1.475 + else
1.476 + start = iPluginChain.Find(aPlugin)-1;
1.477 +
1.478 + if(start!=KErrNotFound)
1.479 + {
1.480 + for(TInt i=start;i>=0;i--)
1.481 + {
1.482 + CFsPlugin* owner = aMsgRequest->iOwnerPlugin;
1.483 + if(owner == iPluginChain[i])
1.484 + break;
1.485 +
1.486 + if(iPluginChain[i]->IsRegistered(function, CFsPlugin::EPostIntercept))
1.487 + {
1.488 + if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive)))
1.489 + {
1.490 +
1.491 + aPlugin = iPluginChain[i];
1.492 + if(aLock)
1.493 + UnlockChain();
1.494 + return KErrNone;
1.495 + }
1.496 + }
1.497 + }
1.498 + }
1.499 + aPlugin = NULL;
1.500 + if(aLock)
1.501 + UnlockChain();
1.502 + return KErrNotFound;
1.503 + }
1.504 +/**
1.505 +Inserts the plugin in the stack (chain)
1.506 +
1.507 +if aPos absolute postion, it simply inserts it
1.508 +if aPos unique position, it walks through chain and checks the unique positions
1.509 +*/
1.510 +TInt FsPluginManager::InsertInPluginStack(CFsPlugin*& aPlugin,TInt aPos)
1.511 + {
1.512 + TInt ret=KErrNone;
1.513 + TInt count= iPluginChain.Count();
1.514 + if(aPos == KPluginAutoLocate)
1.515 + {
1.516 + TInt uPos= aPlugin->iUniquePos;
1.517 + for(TInt i=0;i<count;i++)
1.518 + {
1.519 + if(uPos == iPluginChain[i]->iUniquePos)
1.520 + {
1.521 + return KErrInUse;
1.522 + }
1.523 +
1.524 + if(uPos < iPluginChain[i]->iUniquePos)
1.525 + {
1.526 + ret=iPluginChain.Insert(aPlugin,i);
1.527 + return ret;
1.528 + }
1.529 + }
1.530 + ret=iPluginChain.Append(aPlugin);
1.531 + }
1.532 + else
1.533 + {
1.534 + // Absolute position
1.535 +
1.536 + if(aPos > count)
1.537 + return(KErrNotFound);
1.538 + if(aPos == count)
1.539 + {
1.540 + ret=iPluginChain.Append(aPlugin);
1.541 + return ret;
1.542 + }
1.543 + ret=iPluginChain.Insert(aPlugin,aPos);
1.544 + }
1.545 + return ret;
1.546 + }
1.547 +
1.548 +/**
1.549 +Looks for a plugin in the chain
1.550 +*/
1.551 +TInt FsPluginManager::IsInChain(TInt aUPos,TInt aPos, TInt aDrive, CFsPluginFactory* aPluginFactory)
1.552 + {
1.553 + TInt count= iPluginChain.Count();
1.554 +
1.555 + if(aPos == KPluginAutoLocate)
1.556 + {
1.557 + for(TInt i=0;i<count;i++)
1.558 + {
1.559 + CFsPlugin* pP = iPluginChain[i];
1.560 + if(aPluginFactory->SupportedDrives()&KPluginVersionTwo) //Version2
1.561 + {
1.562 + //If KPluginAutoAttach, then we're dismounted from all drives.
1.563 + //If KPluginMountDriveZ, then check against 25 explicitly (cannot change aDrive:=Z as that==KPluginAutoAttach))
1.564 + //If any other drive mounted.
1.565 + if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || (aDrive==KPluginMountDriveZ && pP->iMountedOn & (1<<EDriveZ)) || pP->iMountedOn & (1<<aDrive)))
1.566 + return i;
1.567 + }
1.568 + else //version1
1.569 + {
1.570 + if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || pP->iMountedOn & (1<<aDrive)))
1.571 + return i;
1.572 + }
1.573 + }
1.574 + return KErrNotFound;
1.575 + }
1.576 +
1.577 + if(aPos+1>iPluginChain.Count())
1.578 + return(KErrNotFound);
1.579 +
1.580 + if(iPluginChain[aPos]->iUniquePos == aUPos && aDrive==iPluginChain[aPos]->Drive())
1.581 + return aPos;
1.582 + return KErrNotFound;
1.583 + }
1.584 +
1.585 +/**
1.586 +Finds a plugin by unique position
1.587 +*/
1.588 +CFsPlugin* FsPluginManager::FindByUniquePosition(TInt aUniquePosition)
1.589 + {
1.590 + LockChain();
1.591 + CFsPlugin* plugin = NULL;
1.592 + TInt count= iPluginChain.Count();
1.593 + for(TInt i=0;i<count;i++)
1.594 + {
1.595 + if(aUniquePosition == iPluginChain[i]->iUniquePos)
1.596 + {
1.597 + plugin = iPluginChain[i];
1.598 + break;
1.599 + }
1.600 + }
1.601 + UnlockChain();
1.602 + return plugin;
1.603 + }
1.604 +
1.605 +/**
1.606 +Create a connection to a plugin
1.607 +*/
1.608 +CFsPluginConn* FsPluginManager::CreatePluginConnL(TInt aUniquePosition, TUint aClientId)
1.609 + {
1.610 + CFsPlugin* pP = FindByUniquePosition(aUniquePosition);
1.611 + if(pP != NULL)
1.612 + {
1.613 + CFsPluginConn* pC = pP->NewPluginConnL();
1.614 + CleanupStack::PushL(pC);
1.615 + pC->iPluginP = pP;
1.616 + pC->iClientId = aClientId;
1.617 + iPluginConns->AddL(pC, ETrue);
1.618 + CleanupStack::Pop(pC);
1.619 + return pC;
1.620 + }
1.621 +
1.622 + User::Leave(KErrNotFound);
1.623 + return NULL;
1.624 + }
1.625 +
1.626 +/**
1.627 +Create a plugin thread
1.628 +Should only by called from main file server thread with plugin thread unavailable
1.629 +*/
1.630 +TInt FsPluginManager::InitPlugin(CFsPlugin& aPlugin)
1.631 + {
1.632 + TInt err = KErrNone;
1.633 +
1.634 + if(!aPlugin.iThreadP)
1.635 + {
1.636 + TRAP(err,aPlugin.iThreadP=CPluginThread::NewL(aPlugin));
1.637 + if(err!=KErrNone)
1.638 + return err;
1.639 + }
1.640 +
1.641 + aPlugin.iThreadId = aPlugin.iThreadP->StartL();
1.642 + return err;
1.643 + }
1.644 +/**
1.645 +Cancels plugin requests
1.646 +*/
1.647 +void FsPluginManager::CancelPlugin(CFsPlugin* aPlugin,CSessionFs* aSession)
1.648 + {
1.649 + aPlugin->iThreadP->CompleteSessionRequests(aSession,KErrCancel);
1.650 + }
1.651 +
1.652 +/**
1.653 +Gets number of plugins in the plugin stack
1.654 +*/
1.655 +TInt FsPluginManager::ChainCount()
1.656 + {
1.657 + return(iPluginChain.Count());
1.658 + }
1.659 +
1.660 +/**
1.661 + * Returns a CFsPlugin* from aPos in the plugin chain.
1.662 + *
1.663 + * To be called whilst already holding the iChainLock.
1.664 + *
1.665 + * @returns (via parameter) CFsPlugin*& aPlugin
1.666 +*/
1.667 +TInt FsPluginManager::Plugin(CFsPlugin*& aPlugin, TInt aPos)
1.668 + {
1.669 + if(aPos >= iPluginChain.Count() || aPos < 0)
1.670 + return KErrNotFound;
1.671 +
1.672 + aPlugin = iPluginChain[aPos];
1.673 + return KErrNone;
1.674 + }
1.675 +
1.676 +/**
1.677 +Locks the chain
1.678 +*/
1.679 +void FsPluginManager::LockChain()
1.680 + {
1.681 + iChainLock.Wait();
1.682 + }
1.683 +
1.684 +/**
1.685 +Unlocks the chain
1.686 +*/
1.687 +void FsPluginManager::UnlockChain()
1.688 + {
1.689 + iChainLock.Signal();
1.690 + }
1.691 +
1.692 +/**
1.693 +Gets plugin conn from handle
1.694 +*/
1.695 +CFsPluginConn* FsPluginManager::GetPluginConnFromHandle(CSessionFs* aSession, TInt aHandle)
1.696 + {
1.697 + return((CFsPluginConn*)(SessionObjectFromHandle(aHandle,iPluginConns->UniqueID(),aSession)));
1.698 + }
1.699 +
1.700 +/**
1.701 +Checks if the current thread is plugin conn's thread
1.702 +*/
1.703 +TBool FsPluginManager::IsPluginConnThread(TThreadId tid, CFsPlugin* aPlugin)
1.704 + {
1.705 + iPluginConns->Lock();
1.706 + TInt count = iPluginConns->Count();
1.707 + while(count--)
1.708 + {
1.709 + CFsPluginConn* conn = (CFsPluginConn*)(*iPluginConns)[count];
1.710 + if(conn->Plugin() == aPlugin)
1.711 + {
1.712 + if(conn->ClientId() == tid)
1.713 + {
1.714 + iPluginConns->Unlock();
1.715 + return ETrue;
1.716 + }
1.717 + }
1.718 + }
1.719 + iPluginConns->Unlock();
1.720 + return EFalse;
1.721 + }
1.722 +
1.723 +/**
1.724 +Dispatch a synchronous message
1.725 +*/
1.726 +void FsPluginManager::DispatchSync(CFsRequest* aRequest)
1.727 + {
1.728 + __THRD_PRINT(_L("FsPluginManager::DispatchSync"));
1.729 + if(!FsThreadManager::IsMainThread() && iScheduler)
1.730 + {
1.731 + iScheduler->Dispatch(aRequest);
1.732 + }
1.733 + else
1.734 + {
1.735 + aRequest->Process();
1.736 + }
1.737 + }
1.738 +
1.739 +void FsPluginManager::CompleteSessionRequests(CSessionFs* aSession, TInt aValue, CFsInternalRequest* aRequest)
1.740 +/**
1.741 + * Complete outstanding requests for the specified session
1.742 + */
1.743 + {
1.744 + __PRINT2(_L("FsPluginManager::CompleteSessionRequests(%08x, %d)"), aSession, aValue);
1.745 +
1.746 + // Iterate through all plugins, cancelling outstanding session requests
1.747 + aRequest->Set(CancelPluginOp, aSession);
1.748 +
1.749 + FsPluginManager::LockChain();
1.750 + TInt count = FsPluginManager::ChainCount();
1.751 + TInt i;
1.752 + for(i=0; i<count; i++)
1.753 + {
1.754 + CFsPlugin* plugin = NULL;
1.755 + User::LeaveIfError(FsPluginManager::Plugin(plugin, i));
1.756 + __ASSERT_DEBUG(plugin, User::Leave(KErrNotFound));
1.757 + aRequest->iCurrentPlugin = plugin;
1.758 + aRequest->Status() = KRequestPending;
1.759 + aRequest->Dispatch();
1.760 + //Cancel is delivered to the front of the request queue
1.761 + //so hopefully this wont take too long.
1.762 + FsPluginManager::UnlockChain();
1.763 + User::WaitForRequest(aRequest->Status());
1.764 + FsPluginManager::LockChain();
1.765 + __ASSERT_ALWAYS(aRequest->Status().Int()==KErrNone||aRequest->Status().Int()==KErrCancel,Fault(ESessionDisconnectThread2));
1.766 + count = FsPluginManager::ChainCount();
1.767 + }
1.768 + FsPluginManager::UnlockChain();
1.769 +
1.770 +// RDebug::Print(_L("FsPluginManager::CompleteSessionRequests - CSRs"));
1.771 + iScheduler->CompleteSessionRequests(aSession, aValue);
1.772 + }
1.773 +
1.774 +