userlibandfileserver/fileserver/sfile/sf_plugin_man.cpp
changeset 0 a41df078684a
child 2 4122176ea935
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfile\sf_plugin.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32std.h>
       
    19 #include "sf_std.h"
       
    20 #include "sf_plugin_priv.h"
       
    21 
       
    22 CFsObjectCon* FsPluginManager::iPluginFactories = NULL;
       
    23 CFsObjectCon* FsPluginManager::iPluginConns     = NULL;
       
    24 RFastLock FsPluginManager::iChainLock;
       
    25 RPointerArray<CFsPlugin> FsPluginManager::iPluginChain;
       
    26 CFsSyncMessageScheduler* FsPluginManager::iScheduler = NULL;
       
    27 
       
    28 TBool IsPagableDrive(TInt aDrive)
       
    29 	{
       
    30 	if(LocalDrives::IsValidDriveMapping(aDrive))
       
    31 		{
       
    32 		TLocalDriveCapsBuf capsBuf;	
       
    33 		if(!LocalDrives::IsProxyDrive(aDrive) && LocalDrives::GetLocalDrive(aDrive).Caps(capsBuf) && capsBuf().iDriveAtt & KDriveAttPageable)
       
    34 			{
       
    35 			return (TBool)ETrue;
       
    36 			}
       
    37 		}
       
    38 	return (TBool) EFalse;
       
    39 	}
       
    40 
       
    41 /*
       
    42 @param aNonPagableDriveMask - a drive mask of the drives a plugin wishes to mount on
       
    43 @return A drive mask of the drives a plugin wishes to mount on not containing any pagable drives.
       
    44 */
       
    45 TInt NonPagableDrivesMask(TInt aNonPagableDriveMask)
       
    46 	{
       
    47 	TInt driveMask = aNonPagableDriveMask;
       
    48 	for(TInt i = 0; i < KMaxDrives; i++)
       
    49 		{
       
    50 		//If we're interested in this drive
       
    51 		if((aNonPagableDriveMask & 1<<i) && IsPagableDrive(i)) 
       
    52 			{
       
    53 			driveMask ^= 1<<i; //remove this drive
       
    54 			}
       
    55 		}
       
    56 	return driveMask;
       
    57 	}
       
    58 
       
    59 TInt FsPluginManager::UpdateMountedDrive(CFsPlugin* aPlugin, CFsPluginFactory* aFactory,TInt aDrive)
       
    60 	{
       
    61 	if(aDrive==KPluginAutoAttach) //KPluginAutoAttach
       
    62 		{
       
    63 		if(!(aFactory->SupportedDrives()&KPluginVersionTwo)) 
       
    64 			{ //Version 1 Plugin - Mount on all (except Z and pagble drives) 
       
    65 			TInt drivesAToY = (KPluginSupportAllDrives>>1);
       
    66 			aPlugin->iMountedOn = NonPagableDrivesMask(drivesAToY);
       
    67 			}
       
    68 		else 
       
    69 			{ //Version 2 Plugin - Mount on what the plugin supports (except pagable drives)
       
    70 			aPlugin->iMountedOn = NonPagableDrivesMask((aFactory->SupportedDrives()&(~KPluginVersionTwo)));
       
    71 			}
       
    72 		
       
    73 		if(!(aPlugin->iMountedOn &(~KPluginVersionTwo))) 
       
    74 			{ //Are we mounted on anything?
       
    75 			return KErrNotSupported;
       
    76 			}
       
    77 		return KErrNone;
       
    78 		}
       
    79 	
       
    80 	// DriveZ special handling
       
    81 	if(aDrive==KPluginMountDriveZ)
       
    82 		aDrive = EDriveZ;
       
    83 	
       
    84 	//Mounting on a single drive
       
    85 	if(!IsPagableDrive(aDrive))
       
    86 		{
       
    87 		aPlugin->iMountedOn |= 1<<aDrive;
       
    88 		return KErrNone;
       
    89 		}
       
    90 
       
    91 	return KErrNotSupported;
       
    92 	}
       
    93 
       
    94 /**
       
    95 FsPluginManager::Initialise
       
    96 */
       
    97 void FsPluginManager::InitialiseL()
       
    98 	{
       
    99 	iPluginFactories = TheContainer->CreateL();
       
   100 	iPluginConns = TheContainer->CreateL();
       
   101 	iPluginChain.Reset();
       
   102 	User::LeaveIfError(iChainLock.CreateLocal());
       
   103 
       
   104 	// Create and install the synchronous message scheduler
       
   105 	//  - Messages are dispatched here from plugin threads if they are
       
   106 	//	  to be executed in the context of the main file server thread.
       
   107 	iScheduler = CFsSyncMessageScheduler::NewL();
       
   108 	iScheduler->RunL();
       
   109 	}
       
   110 
       
   111 /**
       
   112 FsPluginManager::MountPlugin
       
   113 */
       
   114 TInt FsPluginManager::MountPlugin(CFsPluginFactory& aPluginFactory, TInt aDrive, TInt aPos)
       
   115 	{
       
   116 	TInt uniquePosition = aPluginFactory.UniquePosition();
       
   117 	CFsPlugin* pP = NULL;
       
   118 	CFsPluginFactory* pF = &aPluginFactory;
       
   119 	
       
   120 	//Version1 plugins could either been mounted on 1 or all drives.
       
   121 	//This isn't particularily desirable.
       
   122 	// Thus -
       
   123 	//For version2 plugins:
       
   124 	//Check whether this plugin has already been mounted
       
   125 	pP = FindByUniquePosition(uniquePosition);
       
   126 	if(pP && (aPluginFactory.iSupportedDrives&KPluginVersionTwo))
       
   127 		{
       
   128 		//if this plugin has already been mounted then 
       
   129 		//Instead of trying to mount and failing with KErrInUse,
       
   130 		//lets update the iMountedOn instead.
       
   131 		return UpdateMountedDrive(pP,pF,aDrive);
       
   132 		}
       
   133 	
       
   134 	
       
   135 	TRAPD(err, pP = aPluginFactory.NewPluginL());
       
   136 	if(err != KErrNone)
       
   137 		{
       
   138 		if(pP)
       
   139 			pP->Close();
       
   140 		return err;
       
   141 		}
       
   142 
       
   143 	TFullName name = aPluginFactory.Name();
       
   144 	pP->SetName(&name);
       
   145 	pP->iUniquePos=aPluginFactory.UniquePosition();
       
   146 	pP->SetDrive(aDrive);
       
   147 	
       
   148 	//Set which drive(s?) this plugin is mounted on.
       
   149 	err = UpdateMountedDrive(pP,pF,aDrive);
       
   150 	if(err != KErrNone)
       
   151 		{
       
   152 		pP->Close();
       
   153 		return err;
       
   154 		}
       
   155 
       
   156 	LockChain();
       
   157 	err = InsertInPluginStack(pP,aPos);
       
   158 	UnlockChain();
       
   159 	if(err != KErrNone)
       
   160 		{
       
   161 		pP->Close();
       
   162 		return err;
       
   163 		}
       
   164 
       
   165 	err = InitPlugin(*pP);
       
   166 	if(err != KErrNone)
       
   167 		{
       
   168 		pP->Close();
       
   169 		return err;
       
   170 		}
       
   171  	aPluginFactory.IncrementMounted();
       
   172 
       
   173 	return KErrNone;
       
   174 	}
       
   175 
       
   176 /**
       
   177 Dismounts a plugin
       
   178 Must be called with the plugin chain locked.
       
   179 */
       
   180 void FsPluginManager::DismountPlugin(CFsPluginFactory& aPluginFactory,TInt aPos)
       
   181 	{
       
   182 	CFsPlugin* plugin=iPluginChain[aPos];
       
   183 
       
   184 	if (plugin != NULL)
       
   185 		{
       
   186 		// Check if there is any requests for this plugin
       
   187 		// if so, deliver them to the next supporting plugin
       
   188 		TransferRequests(plugin->iThreadP);
       
   189 
       
   190 		plugin->iThreadP=NULL;
       
   191 
       
   192 		iPluginChain.Remove(aPos);
       
   193 		iPluginChain.Compress();
       
   194 
       
   195 		//Need this to remove it from container
       
   196 		//plugin->Close() deletes plugin.
       
   197  		plugin->Close();
       
   198 		plugin=NULL;
       
   199 		}
       
   200 	else
       
   201 		{
       
   202 		ASSERT(0);	// force panic in debug mode
       
   203 		}
       
   204 
       
   205 	aPluginFactory.DecrementMounted();
       
   206 	}
       
   207 
       
   208 /*
       
   209  * This will iterate through a plugins request queue and 
       
   210  * search for the first occurance it finds of a CancelPluginOp
       
   211  * request.
       
   212  */
       
   213 void FsPluginManager::GetNextCancelPluginOpRequest(CPluginThread* aPluginThread, CFsRequest*& aCancelPluginRequest)
       
   214     {
       
   215     __THRD_PRINT(_L("FsPluginManager::GetNextCancelPluginOpRequest"));
       
   216     
       
   217     TDblQueIter<CFsRequest> iter(aPluginThread->iList);
       
   218     CFsRequest* request = NULL;
       
   219 
       
   220     while((request=iter++)!=NULL)
       
   221         {
       
   222         if(request->Operation()->iFunction == KCancelPlugin)
       
   223             {
       
   224             aCancelPluginRequest = request;
       
   225             break;
       
   226             }
       
   227         }
       
   228     }
       
   229  
       
   230 
       
   231 
       
   232 
       
   233 
       
   234 /**
       
   235 Transfer any outstanding requests to next/previous plugin depending on
       
   236 if it is post filter or not
       
   237 */
       
   238 void FsPluginManager::TransferRequests(CPluginThread* aPluginThread)
       
   239 	{
       
   240 	aPluginThread->iListLock.Wait();
       
   241 	
       
   242 	__THRD_PRINT(_L("FsPluginManager::TransferRequests - moving requests"));
       
   243 	
       
   244 	/*
       
   245 	 * We are transferring requests up and down the chain
       
   246 	 * because this plugin is being removed.
       
   247 	 * 
       
   248 	 * There is a potential problem when one of the outstanding requests
       
   249 	 * is CancelPluginOp which is called when the Session is being closed.
       
   250 	 * The CancelPluginOp will try to cancel all of the requests on a plugin's
       
   251 	 * queue which is associated with that session.
       
   252 	 * DismountPlugin(and thus TransferRequests) is trying to preserve the requests
       
   253 	 * by passing them along to the Next/Previous plugins. 
       
   254 	 * 
       
   255 	 * If there is a cancel in the chain we must NOT pass any requests to Previous Plugins 
       
   256 	 * as these have already had their chains emptied.
       
   257 	 * We should also be wary of passing requests up the chain as they will simply be cancelled 
       
   258 	 * somewhere closer to the drive [thread].
       
   259 	 * 
       
   260 	 * Therefore, we shall check whether there is a KCancelPlugin op in the 
       
   261 	 * chain first. 
       
   262      * If there is a cancelPluginOp in the chain, we will cancel of the requests 
       
   263      * that are associated with that session.
       
   264      * 
       
   265      * After that is out of the way we preserve the remaining requests for different sessions by
       
   266      * passing them on.
       
   267 	 */
       
   268 	if(!aPluginThread->iList.IsEmpty())
       
   269 	    {
       
   270 	    CFsRequest* cancelRequest = NULL;
       
   271 	    //For every CancelPluginOp 
       
   272 	    while(FsPluginManager::GetNextCancelPluginOpRequest(aPluginThread, cancelRequest), cancelRequest!=NULL)
       
   273 	        {
       
   274 	        RDebug::Print(_L("Transferring Plugin Requests - CancelPluginOp"));
       
   275 	        TDblQueIter<CFsRequest> iter(aPluginThread->iList);
       
   276 	        CFsRequest* request = NULL;
       
   277 	        //For every request
       
   278 	        while((request=iter++)!=NULL)
       
   279 	            {
       
   280 	            if(request->Session() == cancelRequest->Session() && request != cancelRequest)
       
   281 	                {
       
   282 	                request->iLink.Deque();
       
   283 	                request->Complete(KErrCancel);
       
   284 	                }
       
   285 	            }
       
   286 	        cancelRequest->iLink.Deque();
       
   287 	        cancelRequest->Complete(KErrNone);
       
   288 	        cancelRequest = NULL;
       
   289 	        }
       
   290 
       
   291 	    /*
       
   292 	     * Now that all requests that were to be cancelled have been cancelled,
       
   293 	     * we can now go about moving the remaining ones on to , or back to, 
       
   294 	     * the appropriate next or previous plugins.
       
   295 	     * 
       
   296 	     * ToDo: This next 'while' might be able to be replaced with a call to
       
   297 	     * DispatchToPlugin/DispatchToDrive instead.
       
   298 	     */
       
   299 	    while(!aPluginThread->iList.IsEmpty())
       
   300 	        {
       
   301 	        CFsRequest* pR=aPluginThread->iList.First();
       
   302 	        CFsMessageRequest& mR = *(CFsMessageRequest*) pR;
       
   303 	        pR->iLink.Deque();
       
   304 	        pR->iCurrentPlugin=NULL;
       
   305 
       
   306 	        if(pR->IsPluginSpecific())
       
   307 	            {
       
   308 	            pR->Complete(KErrCancel);
       
   309 	            continue;
       
   310 	            }
       
   311 
       
   312 	        if(pR->IsPostOperation())
       
   313 	            {
       
   314 	            //[set the plugin to] pass the request backwards in the chain
       
   315 	            PrevPlugin(pR->iCurrentPlugin, &mR, EFalse);
       
   316 	            }
       
   317 	        else //IsPreOperations
       
   318 	            {
       
   319 	            //[set the plugin to] pass the request forwards in the chain
       
   320 	            NextPlugin(pR->iCurrentPlugin, &mR, EFalse);
       
   321 	            }
       
   322 
       
   323 	        if(pR->iCurrentPlugin)
       
   324 	            {
       
   325 	            pR->iCurrentPlugin->iThreadP->DeliverBack(pR);
       
   326 	            }
       
   327 	        else
       
   328 	            {
       
   329 	            if(!pR->IsPostOperation() && (pR->DriveNumber()>=EDriveA && pR->DriveNumber()<=EDriveZ))
       
   330 	                {
       
   331 	                //Deliver to drive thread
       
   332 	                CDriveThread* dT=NULL;
       
   333 	                TInt r=FsThreadManager::GetDriveThread(pR->DriveNumber(),&dT);
       
   334 	                __ASSERT_ALWAYS(r==KErrNone && dT,Fault(EFsDriveThreadError));
       
   335 	                CRequestThread* pT = (CRequestThread*)dT;
       
   336 	                pT->DeliverBack(pR);
       
   337 	                }
       
   338 	            else
       
   339 	                {
       
   340 	                pR->Complete(KErrCancel);
       
   341 	                }
       
   342 	            }
       
   343 	        }
       
   344 	    }
       
   345 
       
   346 	aPluginThread->iExit = ETrue;
       
   347 	aPluginThread->iListLock.Signal();
       
   348 
       
   349 	__THRD_PRINT(_L("FsPluginManager::TransferRequests - all requests moved/cancelled"));
       
   350 	}
       
   351 
       
   352 /**
       
   353 Install a plugin factory
       
   354 */
       
   355 TInt FsPluginManager::InstallPluginFactory(CFsPluginFactory* aFactory,RLibrary aLib)
       
   356 	{
       
   357 	TInt r=aFactory->Install();
       
   358 	__PRINT1TEMP(_L("InstallPluginFactory %S"),aFactory->Name());
       
   359 	if (r==KErrNone)
       
   360 		{TRAP(r,iPluginFactories->AddL(aFactory,ETrue))}
       
   361 	if (r!=KErrNone)
       
   362 		aFactory->Remove();
       
   363 	if (r==KErrNone)
       
   364 		aFactory->SetLibrary(aLib);
       
   365 	else
       
   366 		aFactory->Close();
       
   367 	return(r);
       
   368 	}
       
   369 
       
   370 /**
       
   371 Find a plugin factory by name
       
   372 */
       
   373 CFsPluginFactory* FsPluginManager::GetPluginFactory(const TDesC& aName)
       
   374 	{
       
   375 
       
   376 	TInt h=0;
       
   377 	TInt r=iPluginFactories->FindByName(h,aName);
       
   378 	if (r!=KErrNone)
       
   379 		return(NULL);
       
   380 	return((CFsPluginFactory*)iPluginFactories->At(h));
       
   381 	}
       
   382 
       
   383 /**
       
   384 Find the next plugin that supports the operation
       
   385 @param aCheckCurrentOperation - Optional, if false, will return the next plugin,
       
   386  								whether the plugin is currently registered
       
   387 								for the current function of not. (so long as mounted on the current drive)
       
   388 */
       
   389 TInt FsPluginManager::NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest,TBool aLock, TBool aCheckCurrentOperation)
       
   390 	{
       
   391 	if(aMsgRequest->DirectToDrive())
       
   392 		{
       
   393 		aPlugin = NULL;
       
   394 		return KErrNotFound;
       
   395 		}
       
   396 
       
   397 	TInt r = KErrNone;
       
   398 	TInt start;
       
   399 	TInt function = aMsgRequest->Operation()->Function();
       
   400 	TInt drive = aMsgRequest->DriveNumber();
       
   401 
       
   402 	if(aLock)
       
   403 	    LockChain();
       
   404 	
       
   405 	TInt count = iPluginChain.Count();
       
   406 
       
   407 	if(aPlugin == NULL)
       
   408 		start=0;
       
   409 	else
       
   410 		start = iPluginChain.Find(aPlugin)+1;
       
   411 
       
   412 	if(start!=KErrNotFound)
       
   413 		{
       
   414 		for(TInt i=start;i<count;i++)
       
   415 			{
       
   416 			if(!aCheckCurrentOperation || iPluginChain[i]->IsRegistered(function, CFsPlugin::EPreIntercept))
       
   417 				{
       
   418 				if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive))) 
       
   419 					{
       
   420 
       
   421 					aPlugin = iPluginChain[i];
       
   422 					if(aLock)
       
   423 					    UnlockChain();
       
   424 					return(r);
       
   425 					}
       
   426 				}
       
   427 			}
       
   428 		}
       
   429 	aPlugin = NULL;
       
   430 	if(aLock)
       
   431 	    UnlockChain();
       
   432 	return(KErrNotFound);
       
   433 	}
       
   434 
       
   435 /**
       
   436 Find the next plugin that supports the operation
       
   437 */
       
   438 TInt FsPluginManager::PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock)
       
   439 	{
       
   440 	if(aMsgRequest->DirectToDrive() && (aMsgRequest->CurrentOperationPtr() != NULL))
       
   441 		{
       
   442 		aPlugin = NULL;
       
   443 		return KErrNotFound;
       
   444 		}
       
   445 
       
   446 	TInt r = KErrNone;
       
   447 	TInt start;
       
   448 	TInt function = aMsgRequest->Operation()->Function();
       
   449 	TInt drive = aMsgRequest->DriveNumber();
       
   450 
       
   451 	if(aLock)
       
   452 	    LockChain();
       
   453 	
       
   454 	TInt count= iPluginChain.Count();
       
   455 
       
   456 	if(aPlugin == NULL)
       
   457 		start = count-1;
       
   458 	else
       
   459 		start = iPluginChain.Find(aPlugin)-1;
       
   460 
       
   461 	if(start!=KErrNotFound)
       
   462 		{
       
   463 		for(TInt i=start;i>=0;i--)
       
   464 			{
       
   465 			CFsPlugin* owner = aMsgRequest->iOwnerPlugin;
       
   466 			if(owner == iPluginChain[i])
       
   467 				break;
       
   468 
       
   469 			if(iPluginChain[i]->IsRegistered(function, CFsPlugin::EPostIntercept))
       
   470 				{
       
   471 				if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive))) 
       
   472 					{
       
   473 
       
   474 					aPlugin = iPluginChain[i];
       
   475 					if(aLock)
       
   476 					    UnlockChain();
       
   477 					return(r);
       
   478 					}
       
   479 				}
       
   480 			}
       
   481 		}
       
   482 	aPlugin = NULL;
       
   483 	if(aLock)
       
   484 	    UnlockChain();
       
   485 	return(KErrNotFound);
       
   486 	}
       
   487 /**
       
   488 Inserts the plugin in the stack (chain)
       
   489 
       
   490 if aPos absolute postion, it simply inserts it
       
   491 if aPos unique position, it walks through chain and checks the unique positions
       
   492 */
       
   493 TInt FsPluginManager::InsertInPluginStack(CFsPlugin*& aPlugin,TInt aPos)
       
   494 	{
       
   495 	TInt ret=KErrNone;
       
   496 	TInt count= iPluginChain.Count();
       
   497 	if(aPos == KPluginAutoLocate)
       
   498 		{
       
   499 		TInt uPos= aPlugin->iUniquePos;
       
   500 		for(TInt i=0;i<count;i++)
       
   501 			{
       
   502 			if(uPos == iPluginChain[i]->iUniquePos)
       
   503 				{
       
   504 				return KErrInUse;
       
   505 				}
       
   506 
       
   507 			if(uPos < iPluginChain[i]->iUniquePos)
       
   508 				{
       
   509 				ret=iPluginChain.Insert(aPlugin,i);
       
   510 				return ret;
       
   511 				}
       
   512 			}
       
   513 		ret=iPluginChain.Append(aPlugin);
       
   514 		}
       
   515 	else
       
   516 		{
       
   517 		// Absolute position
       
   518 
       
   519 		if(aPos > count)
       
   520 			return(KErrNotFound);
       
   521 		if(aPos == count)
       
   522 			{
       
   523 			ret=iPluginChain.Append(aPlugin);
       
   524 			return ret;
       
   525 			}
       
   526 		ret=iPluginChain.Insert(aPlugin,aPos);
       
   527 		}
       
   528 	return ret;
       
   529 	}
       
   530 
       
   531 /**
       
   532 Looks for a plugin in the chain
       
   533 */
       
   534 TInt FsPluginManager::IsInChain(TInt aUPos,TInt aPos, TInt aDrive, CFsPluginFactory* aPluginFactory)
       
   535 	{
       
   536 	TInt count= iPluginChain.Count();
       
   537 	
       
   538 	if(aPos == KPluginAutoLocate)
       
   539 		{
       
   540 		for(TInt i=0;i<count;i++)
       
   541 			{
       
   542 			CFsPlugin* pP = iPluginChain[i];
       
   543 			if(aPluginFactory->SupportedDrives()&KPluginVersionTwo) //Version2
       
   544 				{
       
   545 				//If KPluginAutoAttach, then we're dismounted from all drives.
       
   546 				//If KPluginMountDriveZ, then check against 25 explicitly (cannot change aDrive:=Z as that==KPluginAutoAttach))
       
   547 				//If any other drive mounted.
       
   548 				if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || (aDrive==KPluginMountDriveZ && pP->iMountedOn & (1<<EDriveZ)) || pP->iMountedOn & (1<<aDrive)))
       
   549 					return i;
       
   550 				}
       
   551 			else //version1
       
   552 				{
       
   553 				if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || pP->iMountedOn & (1<<aDrive)))
       
   554 					return i;
       
   555 				}
       
   556 			}
       
   557 		return KErrNotFound;
       
   558 		}
       
   559 
       
   560 	if(aPos+1>iPluginChain.Count())
       
   561 		return(KErrNotFound);
       
   562 
       
   563 	if(iPluginChain[aPos]->iUniquePos == aUPos && aDrive==iPluginChain[aPos]->Drive())
       
   564 		return aPos;
       
   565 	return KErrNotFound;
       
   566 	}
       
   567 
       
   568 /**
       
   569 Finds a plugin by unique position
       
   570 */
       
   571 CFsPlugin* FsPluginManager::FindByUniquePosition(TInt aUniquePosition)
       
   572 	{
       
   573 	LockChain();
       
   574 	CFsPlugin* plugin = NULL;
       
   575 	TInt count= iPluginChain.Count();
       
   576 	for(TInt i=0;i<count;i++)
       
   577 		{
       
   578 		if(aUniquePosition == iPluginChain[i]->iUniquePos)
       
   579 			{
       
   580 			plugin = iPluginChain[i];
       
   581 			break;
       
   582 			}
       
   583 		}
       
   584 	UnlockChain();
       
   585 	return plugin;
       
   586 	}
       
   587 
       
   588 /**
       
   589 Create a connection to a plugin
       
   590 */
       
   591 CFsPluginConn* FsPluginManager::CreatePluginConnL(TInt aUniquePosition, TUint aClientId)
       
   592 	{
       
   593 	CFsPlugin* pP = FindByUniquePosition(aUniquePosition);
       
   594 	if(pP != NULL)
       
   595 		{
       
   596 		CFsPluginConn* pC = pP->NewPluginConnL();
       
   597 		pC->iPluginP = pP;
       
   598 		pC->iClientId = aClientId;
       
   599 		iPluginConns->AddL(pC, ETrue);
       
   600 		return pC;
       
   601 		}
       
   602 
       
   603 	User::Leave(KErrNotFound);
       
   604 	return NULL;
       
   605 	}
       
   606 
       
   607 /**
       
   608 Create a plugin thread
       
   609 Should only by called from main file server thread with plugin thread unavailable
       
   610 */
       
   611 TInt FsPluginManager::InitPlugin(CFsPlugin& aPlugin)
       
   612 	{
       
   613 	TInt err = KErrNone;
       
   614 
       
   615 	if(!aPlugin.iThreadP)
       
   616 		{
       
   617 		TRAP(err,aPlugin.iThreadP=CPluginThread::NewL(aPlugin));
       
   618 		if(err!=KErrNone)
       
   619 			return err;
       
   620 		}
       
   621 
       
   622 	aPlugin.iThreadId = aPlugin.iThreadP->StartL();
       
   623 	return err;
       
   624 	}
       
   625 /**
       
   626 Cancels plugin requests
       
   627 */
       
   628 void FsPluginManager::CancelPlugin(CFsPlugin* aPlugin,CSessionFs* aSession)
       
   629 	{
       
   630 	aPlugin->iThreadP->CompleteSessionRequests(aSession,KErrCancel);
       
   631 	}
       
   632 
       
   633 /**
       
   634 Gets number of plugins in the plugin stack
       
   635 */
       
   636 TInt FsPluginManager::ChainCount()
       
   637 	{
       
   638 	return(iPluginChain.Count());
       
   639 	}
       
   640 
       
   641 /**
       
   642  * Returns a CFsPlugin* from aPos in the plugin chain.
       
   643  * 
       
   644  * To be called whilst already holding the iChainLock.
       
   645  * 
       
   646  * @returns (via parameter) CFsPlugin*& aPlugin
       
   647 */
       
   648 TInt FsPluginManager::Plugin(CFsPlugin*& aPlugin, TInt aPos)
       
   649 	{
       
   650 	if(aPos >= iPluginChain.Count() || aPos < 0)
       
   651 	    return KErrNotFound;
       
   652 	
       
   653 	aPlugin = iPluginChain[aPos];
       
   654 	return KErrNone;
       
   655 	}
       
   656 
       
   657 /**
       
   658 Locks the chain
       
   659 */
       
   660 void FsPluginManager::LockChain()
       
   661 	{
       
   662 	iChainLock.Wait();
       
   663 	}
       
   664 
       
   665 /**
       
   666 Unlocks the chain
       
   667 */
       
   668 void FsPluginManager::UnlockChain()
       
   669 	{
       
   670 	iChainLock.Signal();
       
   671 	}
       
   672 
       
   673 /**
       
   674 Gets plugin conn from handle
       
   675 */
       
   676 CFsPluginConn* FsPluginManager::GetPluginConnFromHandle(CSessionFs* aSession, TInt aHandle)
       
   677 	{
       
   678 	return((CFsPluginConn*)(SessionObjectFromHandle(aHandle,iPluginConns->UniqueID(),aSession)));
       
   679 	}
       
   680 
       
   681 /**
       
   682 Checks if the current thread is plugin conn's thread
       
   683 */
       
   684 TBool FsPluginManager::IsPluginConnThread(TThreadId tid, CFsPlugin* aPlugin)
       
   685 	{
       
   686 	iPluginConns->Lock();
       
   687 	TInt count = iPluginConns->Count();
       
   688 	while(count--)
       
   689 		{
       
   690 		CFsPluginConn* conn = (CFsPluginConn*)(*iPluginConns)[count];
       
   691 		if(conn->Plugin() == aPlugin)
       
   692 			{
       
   693 			if(conn->ClientId() == tid)
       
   694 				{
       
   695 				iPluginConns->Unlock();
       
   696 				return ETrue;
       
   697 				}
       
   698 			}
       
   699 		}
       
   700 	iPluginConns->Unlock();
       
   701 	return EFalse;
       
   702 	}
       
   703 
       
   704 /**
       
   705 Dispatch a synchronous message
       
   706 */
       
   707 void FsPluginManager::DispatchSync(CFsRequest* aRequest)
       
   708 	{
       
   709 	__THRD_PRINT(_L("FsPluginManager::DispatchSync"));
       
   710 	if(!FsThreadManager::IsMainThread() && iScheduler)
       
   711 		{
       
   712 		iScheduler->Dispatch(aRequest);
       
   713 		}
       
   714 	else
       
   715 		{
       
   716 		aRequest->Process();
       
   717 		}
       
   718 	}
       
   719 
       
   720 void FsPluginManager::CompleteSessionRequests(CSessionFs* aSession, TInt aValue, CFsInternalRequest* aRequest)
       
   721 /**
       
   722 Complete outstanding requests for the specified session
       
   723 */
       
   724 	{
       
   725 	__PRINT2(_L("FsPluginManager::CompleteSessionRequests(%08x, %d)"), aSession, aValue);
       
   726 
       
   727 	// Iterate through all plugins, cancelling outstanding session requests
       
   728 	aRequest->Set(CancelPluginOp, aSession);
       
   729 
       
   730 	FsPluginManager::LockChain();
       
   731 	TInt count = FsPluginManager::ChainCount();
       
   732 	TInt i;
       
   733 	for(i=0; i<count; i++)
       
   734 	    {
       
   735 	    CFsPlugin* plugin = NULL;
       
   736 	    User::LeaveIfError(FsPluginManager::Plugin(plugin, i));
       
   737 	    __ASSERT_DEBUG(plugin, User::Leave(KErrNotFound));
       
   738 	    aRequest->iCurrentPlugin = plugin;
       
   739 	    aRequest->Status() = KRequestPending;
       
   740 	    aRequest->Dispatch();
       
   741 	    //Cancel is delivered to the front of the request queue
       
   742 	    //so hopefully this wont take too long.
       
   743 	    FsPluginManager::UnlockChain();
       
   744 	    User::WaitForRequest(aRequest->Status());
       
   745 	    FsPluginManager::LockChain();
       
   746 	    __ASSERT_ALWAYS(aRequest->Status().Int()==KErrNone||aRequest->Status().Int()==KErrCancel,Fault(ESessionDisconnectThread2));
       
   747 	    count = FsPluginManager::ChainCount();
       
   748 	    }
       
   749 	FsPluginManager::UnlockChain();
       
   750 	
       
   751 //	RDebug::Print(_L("FsPluginManager::CompleteSessionRequests - CSRs"));
       
   752 	iScheduler->CompleteSessionRequests(aSession, aValue);
       
   753 	}
       
   754 
       
   755