os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_obj.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-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_obj.cpp
    15 // 
    16 //
    17 
    18 #include "sf_std.h"
    19 
    20 const TInt KObjectIxGranularity=8;		
    21 const TInt KObjectConGranularity=8;
    22 const TInt KObjectConIxGranularity=4;
    23 const TInt KObjectIndexMask=0x7fff;
    24 const TInt KObjectMaxIndex=0x7fff;
    25 const TInt KObjectInstanceShift=16;
    26 const TInt KObjectInstanceMask=0x3fff;
    27 const TInt KObjectUniqueIDShift=16;
    28 const TInt KObjectIxMaxHandles=0x8000;
    29 
    30 inline TInt index(TInt aHandle)
    31 	{return(aHandle&KObjectIndexMask);}
    32 inline TInt instance(TInt aHandle)
    33 	{return((aHandle>>KObjectInstanceShift)&KObjectInstanceMask);}
    34 inline TInt instanceLimit(TInt& aCount)
    35 	{return ((aCount&KObjectInstanceMask)==0) ? ((++aCount)&KObjectInstanceMask) : aCount&KObjectInstanceMask;}
    36 inline TInt makeHandle(TInt anIndex,TInt anInstance)
    37 	{return((TInt)((anInstance<<KObjectInstanceShift)|anIndex));}
    38 
    39 inline TInt uniqueID(TInt aHandle)
    40 	{return((aHandle>>KObjectUniqueIDShift)&KObjectInstanceMask);}
    41 inline TInt makeFindHandle(TInt anIndex,TInt anUniqueID)
    42 	{return((TInt)((anUniqueID<<KObjectUniqueIDShift)|anIndex));}
    43 
    44 
    45 CFsObjectConIx* CFsObjectConIx::NewL()
    46 //
    47 // Create an instance of this class.
    48 //
    49 	{
    50 
    51 	return new(ELeave) CFsObjectConIx;
    52 	}
    53 
    54 CFsObjectConIx::CFsObjectConIx()
    55 //
    56 // Constructor
    57 //
    58 	: iNextUniqueID(1)
    59 	{
    60 	}
    61 
    62 CFsObjectConIx::~CFsObjectConIx()
    63 //
    64 // Destructor
    65 //
    66 	{
    67 	if (iCount)
    68 		{
    69 		TInt i=-1;
    70 		while(++i<iCount)
    71 			{
    72 			CFsObjectCon* pS=iContainers[i];
    73 			delete pS;
    74 			}
    75 		}
    76 	delete iContainers;
    77 	}
    78 
    79 void CFsObjectConIx::CreateContainerL(CFsObjectCon*& aContainer)
    80 //
    81 // Actually create the container
    82 //
    83 	{
    84 
    85 	aContainer=CFsObjectCon::NewL();
    86 	aContainer->iUniqueID=iNextUniqueID;
    87 	if (iCount==iAllocated)
    88 		{
    89 		TInt newAlloc=iAllocated+KObjectConIxGranularity;
    90 		iContainers=(CFsObjectCon**)User::ReAllocL(iContainers, newAlloc*sizeof(CFsObjectCon*));
    91 		iAllocated=newAlloc;
    92 		}
    93 	iContainers[iCount++]=aContainer;
    94 	}
    95 
    96 CFsObjectCon* CFsObjectConIx::CreateL()
    97 //
    98 // Create a new container.
    99 //
   100 	{
   101 
   102 	CFsObjectCon* pC=NULL;
   103 	TRAPD(r,CreateContainerL(pC))
   104 	if (r!=KErrNone)
   105 		{
   106 		delete pC;
   107 		User::Leave(r);
   108 		}
   109 	iNextUniqueID++;
   110 	return pC;
   111 	}
   112 
   113 void CFsObjectConIx::Remove(CFsObjectCon* aCon)
   114 //
   115 // Remove a container from the index.
   116 //
   117 	{
   118 	if (!aCon)
   119 		return;
   120 	CFsObjectCon** pS=iContainers;
   121 	CFsObjectCon** pE=pS+iCount;
   122 	while(pS<pE)
   123 		{
   124 		if (*pS==aCon)
   125 			{
   126 			Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CFsObjectCon*));
   127 			TInt newAlloc=--iCount;
   128 			newAlloc=(newAlloc+(KObjectConIxGranularity-1))&~(KObjectConIxGranularity-1);
   129 			if (newAlloc!=iAllocated)
   130 				{
   131 				if (newAlloc)
   132 					iContainers=(CFsObjectCon**)User::ReAlloc(iContainers,newAlloc*sizeof(CFsObjectCon*));
   133 				else
   134 					{
   135 					delete iContainers;
   136 					iContainers=NULL;
   137 					}
   138 				iAllocated=newAlloc;
   139 				}
   140 			delete aCon;
   141 			return;
   142 			}
   143 		pS++;
   144 		}
   145 	Fault(EObjRemoveContainerNotFound);
   146 	}
   147 
   148 
   149 /**
   150 Constructs the object and initializes the reference count to one. 
   151  
   152 Once constructed, a reference counting object cannot be deleted until its 
   153 reference count is reduced to zero. 
   154  
   155 @see CFsObject::Close
   156 */
   157 EXPORT_C CFsObject::CFsObject()
   158 	{
   159 
   160 //	iContainer=NULL;
   161 //	iName=NULL;
   162 	iAccessCount=1;
   163 	}
   164 
   165 
   166 /**
   167 Destructor.
   168  
   169 Deallocates memory associated with this objects name, if a name 
   170 has been set.
   171  
   172 @panic FSERV 104 if the reference count is not zero when
   173        the destructor is called.
   174 */
   175 EXPORT_C  CFsObject::~CFsObject()
   176 	{
   177 	__PRINT1(_L("CFsObject::~CFsObject() 0x%x"),this);
   178 	__ASSERT_ALWAYS(Dec()==0,Fault(EObjDestructorAccessCount));	
   179 	__ASSERT_ALWAYS(!iContainer,Fault(EObjDestructorContainer));
   180 	if(iName)
   181 		User::Free(iName);
   182 	}
   183 
   184 
   185 /**
   186 Opens this reference counting object.
   187 
   188 The default behaviour increments the reference count by one. 
   189 
   190 Where a derived class implements its own version of this function, it must 
   191 either use the protected member function Inc() to increment the reference 
   192 count or make a base call to this function.
   193 
   194 @return KErrNone, or another system-wide error code.
   195 */
   196 
   197 EXPORT_C TInt CFsObject::Open()
   198 	{
   199 	TInt count=Inc();
   200 	(void)count;
   201 	__THRD_PRINT2(_L("CFsObject::Open() object=0x%x count=%d"),this,count);
   202 	__ASSERT_DEBUG(count>=1,Fault(EFsObjectOpen));
   203 	return KErrNone;
   204 	}
   205 
   206 
   207 /**
   208 Removes an assigned container object then deletes this reference
   209 counting object.
   210 */
   211 void CFsObject::DoClose()
   212 	{
   213 	__THRD_PRINT(_L("CFsObject::DoClose()"));
   214 	if(iContainer)
   215 		{
   216 		iContainer->Remove(this,ETrue);
   217 		iContainer=NULL;
   218 		}
   219 	delete(this);
   220 	}
   221 
   222 
   223 /**
   224 Closes this reference counting object.
   225 
   226 The default behaviour decrements the reference count by one. If this becomes 
   227 zero, then the function calls DoClose on this reference counting object.
   228  
   229 Where a derived class implements its own version of this function, it can 
   230 use the protected member functions Dec() & DoClose() or make a base call to 
   231 this function.
   232 
   233 @see CFsObject::DoClose
   234 */
   235 EXPORT_C void CFsObject::Close()
   236 	{
   237 	__THRD_PRINT(_L("CFsObject::Close()"));
   238 	if(Dec()==1)
   239 		DoClose();
   240 	}
   241 
   242 
   243 /**
   244 Determine if this object is within the correct drive thread context 
   245 for file based operations.
   246 
   247 The default behaviour is to return True.
   248 
   249 A derived class implementation is required.
   250 
   251 @return ETrue
   252 */
   253 EXPORT_C TBool CFsObject::IsCorrectThread()
   254 	{
   255 	return(ETrue);
   256 	}
   257 
   258 
   259 
   260 /**
   261 Sets or clears this reference counting object's name.
   262 
   263 To set the name, the specified descriptor must contain the name to be set. 
   264 Once the name has been successfully set, then the specified source descriptor 
   265 can be discarded.
   266 
   267 To clear an existing name, specify a NULL argument.
   268 
   269 @param aName A pointer to the descriptor containing the name to be set, or 
   270              NULL if an existing name is to be cleared.
   271 
   272 @return KErrNone if the function is successful;
   273         KErrNoMemory if there is insufficient memory available.
   274 
   275 @panic USER 11 if the length of aName is greater than KMaxName
   276        for a 16-bit descriptor.
   277 @panic USER 23 if the length of aName is greater than KMaxName
   278        for an 8-bit descriptor.
   279 */
   280 EXPORT_C TInt CFsObject::SetName(const TDesC *aName)
   281 	{
   282 	User::Free(iName);
   283 	iName=NULL;
   284 	if (aName!=NULL)
   285 		{
   286 		iName=aName->Alloc();
   287 		if (iName==NULL)
   288 			return(KErrNoMemory);
   289 		}
   290 	return(KErrNone);
   291 	}
   292 
   293 
   294 /**
   295 Gets the name of this reference counting object.
   296 
   297 The default behaviour provided by this function depends on whether a name 
   298 has been explicitly set into the object:
   299 
   300 If a name has previously been set, then the function returns that name.
   301 
   302 If a name has not been set, then the function returns NULL.
   303 
   304 @return A modifiable buffer descriptor with a defined maximum length containing 
   305         the name of this reference counting object or a TName with no contents.
   306 */
   307 EXPORT_C TName CFsObject::Name() const
   308 	{
   309 	if (iName)
   310 		return(*iName);
   311 	
   312 	TName empty;
   313 	return empty;
   314 	}
   315 
   316 
   317 /**
   318 Gets the Unique ID of the assigned object container to this object.
   319 
   320 @return A unique number for file system container objects.
   321 */
   322 TInt CFsObject::UniqueID() const {return(iContainer->UniqueID());}
   323 
   324 
   325 CFsObjectIx* CFsObjectIx::NewL()
   326 //
   327 // Create an instance of this class.
   328 //
   329 	{
   330 	CFsObjectIx* pO=new(ELeave) CFsObjectIx;
   331 	TInt r=pO->iLock.CreateLocal();
   332 	if(r!=KErrNone)
   333 		{
   334 		delete(pO);
   335 		User::Leave(r);
   336 		}
   337 	return(pO);
   338 	}
   339 
   340 CFsObjectIx::CFsObjectIx()
   341 //
   342 // Constructor
   343 //
   344 	: iNextInstance(1)
   345 	{
   346 //	iAllocated=0;
   347 //	iNumEntries=0;
   348 //	iHighWaterMark=0;
   349 //	iObjects=NULL;
   350 	}
   351 
   352 
   353 /**
   354     Close all objects that were created in the main file server thread.
   355     For sync. drives all objects must be closed in the main file server thread, because
   356     they are created in this thread, as soon as all synch. requests are processed there.
   357 */
   358 void CFsObjectIx::CloseMainThreadObjects()
   359 	{
   360 	__ASSERT_DEBUG(FsThreadManager::IsMainThread(),Fault(EObjectIxMainThread));
   361 	__PRINT(_L("CFsObjectIx::CloseThreadObjects()"));
   362     
   363 	Lock();
   364 	// We have to be very careful here. Calling Close() on the objects in the array
   365 	// may result in other entries being removed from the array before we delete
   366 	// them here, and may result in the array being ReAlloc()ed, corrupting the removed
   367 	// entries, hence we must check the iHighWaterMark value each time round the loop.
   368 	TInt i=-1;
   369 	while(++i<iHighWaterMark)
   370 		{
   371 		SFsObjectIxRec* pS=iObjects+i;
   372 		CFsObject *pO=pS->obj;
   373 		if (pO && pO->IsCorrectThread())
   374 			{
   375 			// invalidate entry before closing it
   376 			pS->obj=NULL;
   377 			pO->Close();	
   378 			}
   379 		}
   380 	Unlock();
   381 	}
   382 
   383 
   384 CFsObjectIx::~CFsObjectIx()
   385 //
   386 // Destructor
   387 // Assumes that no need to lock
   388 //
   389 	{
   390 	__PRINT1(_L("CFsObjectIx::~CFsObjectIx() 0x%x"),this);
   391     
   392 	// We have to be very careful here. Calling Close() on the objects in the array
   393 	// may result in other entries being removed from the array before we delete
   394 	// them here, and may result in the array being ReAlloc()ed, corrupting the removed
   395 	// entries, hence we must check the iHighWaterMark value each time round the loop.
   396 	TInt i=-1;
   397 	while(++i<iHighWaterMark)
   398 		{
   399 		SFsObjectIxRec* pS=iObjects+i;
   400 		CFsObject *pO=pS->obj;
   401 		if (pO)
   402 			{
   403 			// invalidate entry before closing it
   404 			pS->obj=NULL;
   405 			pO->Close();	
   406 			}
   407 		}
   408 	delete iObjects;
   409 	iLock.Close();
   410 	}
   411 
   412 TInt CFsObjectIx::AddL(CFsObject* anObj,TBool aLock)
   413 //
   414 // Add a new object to the index.
   415 //
   416 	{
   417 	if(aLock)
   418 		Lock();
   419 	SFsObjectIxRec *pS=iObjects;
   420 	SFsObjectIxRec *pE=pS+iHighWaterMark;
   421 	TInt i=0;
   422 	TInt inc=0;
   423 	while(pS<pE && pS->obj)
   424 		pS++, i++;
   425 	if (pS==pE)
   426 		inc=1;
   427 	if (pS==pE && iAllocated==iHighWaterMark)
   428 		{
   429 		// no slots free, so reallocate array
   430 		if (iHighWaterMark==KObjectIxMaxHandles)
   431 			{
   432 			if(aLock)
   433 				Unlock();
   434 			User::LeaveNoMemory();
   435 			}
   436 		TInt newAlloc=iAllocated + KObjectIxGranularity;
   437 		SFsObjectIxRec* pA=(SFsObjectIxRec*)User::ReAlloc(iObjects, newAlloc*sizeof(SFsObjectIxRec));
   438 		if(!pA)
   439 			{
   440 			if(aLock)
   441 				Unlock();
   442 			User::Leave(KErrNoMemory);
   443 			}
   444 		iObjects=pA;
   445 		iAllocated=newAlloc;
   446 		i=iHighWaterMark;
   447 		pS=pA+i;
   448 		}
   449 	pS->obj=anObj;
   450 	pS->uniqueID=(TUint16)anObj->UniqueID();
   451 	pS->instance=(TUint16)instanceLimit(iNextInstance);
   452 	iNextInstance++;
   453 	iHighWaterMark+=inc;
   454 	++iNumEntries;
   455 	TInt h=makeHandle(i,pS->instance);
   456 	if(aLock)
   457 		Unlock();
   458 	return(h);
   459 	}
   460 
   461 void CFsObjectIx::Remove(TInt aHandle,TBool aLock)
   462 //
   463 // Remove an object from the index.
   464 //
   465 	{
   466 	if(aLock)
   467 		Lock();
   468 	TInt i=index(aHandle);
   469 	__ASSERT_ALWAYS(i<iHighWaterMark,Fault(EObjRemoveBadHandle));
   470 	SFsObjectIxRec* pR=iObjects+i;
   471 	CFsObject *pO=pR->obj;
   472 	if (!pO || pR->instance!=instance(aHandle) || pR->uniqueID!=pO->UniqueID())
   473 		Fault(EObjRemoveBadHandle);
   474 	pR->obj=NULL;
   475 	--iNumEntries;
   476 	if (i==iHighWaterMark-1)
   477 		{
   478 		do
   479 			{
   480 			i--;
   481 			pR--;
   482 			} while(i>=0 && !pR->obj);
   483 		TInt newAlloc=(i+KObjectIxGranularity)&~(KObjectIxGranularity-1);
   484 		if (newAlloc!=iAllocated)
   485 			{
   486 			if (newAlloc)
   487 				iObjects=(SFsObjectIxRec*)User::ReAlloc(iObjects,newAlloc*sizeof(SFsObjectIxRec));
   488 			else
   489 				{
   490 				delete iObjects;
   491 				iObjects=NULL;
   492 				}
   493 			iAllocated=newAlloc;
   494 			}
   495 		iHighWaterMark=i+1;
   496 		}
   497 	if(aLock)
   498 		Unlock();
   499 	pO->Close();
   500 	}
   501 
   502 CFsObject *CFsObjectIx::At(TInt aHandle,TInt aUniqueID,TBool aLock)
   503 //
   504 // Return the object from its handle.
   505 //
   506 	{
   507 	if(aLock)
   508 		Lock();
   509 	TInt i=index(aHandle);
   510 	if (i>=iHighWaterMark)
   511 		{
   512 		if(aLock)
   513 			Unlock();
   514 		return NULL;
   515 		}
   516 	SFsObjectIxRec *pS=iObjects+i;
   517 	if (pS->instance!=instance(aHandle) || pS->uniqueID!=aUniqueID)
   518 		{
   519 		if(aLock)
   520 			Unlock();
   521 		return NULL;
   522 		}
   523 	if(aLock)
   524 		Unlock();
   525 	return pS->obj;	
   526 	}
   527 
   528 CFsObject *CFsObjectIx::At(TInt aHandle,TBool aLock)
   529 //
   530 // Return the object from its handle.
   531 //
   532 	{
   533 	if(aLock)
   534 		Lock();
   535 	TInt i=index(aHandle);
   536 	if (i>=iHighWaterMark)
   537 		{
   538 		if(aLock)
   539 			Unlock();
   540 		return NULL;
   541 		}
   542 	SFsObjectIxRec *pS=iObjects+i;
   543 	if (pS->instance!=instance(aHandle))
   544 		{
   545 		if(aLock)
   546 			Unlock();
   547 		return NULL;
   548 		}
   549 	if(aLock)
   550 		Unlock();
   551 	return pS->obj;
   552 	}
   553 
   554 TInt CFsObjectIx::At(const CFsObject* anObj,TBool aLock)
   555 //
   556 // Return the handle from an object.
   557 //
   558 	{
   559 	if(aLock)
   560 		Lock();
   561 	if (iHighWaterMark)
   562 		{
   563 		SFsObjectIxRec* pS=iObjects;
   564 		SFsObjectIxRec* pE=pS+iHighWaterMark;
   565 		TInt i=0;
   566 		while(pS<pE && pS->obj!=anObj)
   567 			pS++, i++;
   568 		if (pS<pE)
   569 			{
   570 			TInt h=makeHandle(i,pS->instance);
   571 			if(aLock)
   572 				Unlock();	
   573 			return(h);	
   574 			}
   575 		}
   576 	if(aLock)
   577 		Unlock();
   578 	return KErrNotFound;
   579 	}
   580 
   581 
   582 CFsObject* CFsObjectIx::operator[](TInt anIndex)
   583 //
   584 // Return the object at anIndex
   585 //
   586 	{
   587 
   588 	__ASSERT_ALWAYS(anIndex>=0 && anIndex<iHighWaterMark,Fault(EArrayIndexOutOfRange));
   589 	return iObjects[anIndex].obj;
   590 	}
   591 
   592 CFsObjectCon* CFsObjectCon::NewL()
   593 //
   594 // Create a new instance of this class.
   595 //
   596 	{
   597 	CFsObjectCon* pO=new(ELeave) CFsObjectCon(ENotOwnerID);
   598 	TInt r=pO->iLock.CreateLocal();
   599 	if(r!=KErrNone)
   600 		{
   601 		delete(pO);
   602 		User::Leave(r);
   603 		}
   604 	return(pO);
   605 	}
   606 
   607 CFsObjectCon::CFsObjectCon(TInt aUniqueID)
   608 //
   609 // Constructor
   610 //
   611 	: iUniqueID(aUniqueID)
   612 	{
   613 //	iAllocated=0;
   614 //	iCount=0;
   615 //	iObjects=NULL;
   616 	}
   617 
   618 CFsObjectCon::~CFsObjectCon()
   619 //
   620 // Destructor
   621 //
   622 	{
   623 	__ASSERT_ALWAYS(iCount==0,Fault(EObjectConDestructor));
   624 	iLock.Close();
   625 	delete iObjects;
   626 	}
   627 
   628 void CFsObjectCon::AddL(CFsObject* anObj,TBool aLock)
   629 //
   630 // Install a new object to the container. The full name must be unique.
   631 //
   632 	{
   633 	if(anObj->iName)
   634 		User::LeaveIfError(CheckUniqueName(anObj));
   635 	if(aLock)
   636 		Lock();
   637 	if (iCount==iAllocated)
   638 		{
   639 		TInt newAlloc=iAllocated+KObjectConGranularity;
   640 		CFsObject** pO=(CFsObject**)User::ReAlloc(iObjects, newAlloc*sizeof(CFsObject*));
   641 		if(!pO)
   642 			{
   643 			if(aLock)
   644 				Unlock();
   645 			User::Leave(KErrNoMemory);
   646 			}
   647 		iObjects=pO;
   648 		iAllocated=newAlloc;
   649 		}
   650 	iObjects[iCount++]=anObj;
   651 	if (iUniqueID!=ENotOwnerID)
   652 		anObj->iContainer=this;
   653 	if(aLock)
   654 		Unlock();
   655 	}
   656 
   657 void CFsObjectCon::Remove(CFsObject *anObj,TBool aLock)	
   658 //
   659 // Remove an object from the container.
   660 // This assumes that close is called by the calling function
   661 // 
   662 	{
   663 	if(aLock)
   664 		Lock();
   665 	CFsObject** pS=iObjects;
   666 	CFsObject** pE=pS+iCount;
   667 	while(pS<pE)
   668 		{
   669 		if (*pS==anObj)
   670 			{
   671 			Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CFsObject*));
   672 			TInt newAlloc=--iCount;
   673 			newAlloc=(newAlloc+(KObjectConGranularity-1))&~(KObjectConGranularity-1);
   674 			if (newAlloc!=iAllocated)
   675 				{
   676 				if (newAlloc)
   677 					iObjects=(CFsObject**)User::ReAlloc(iObjects,newAlloc*sizeof(CFsObject*));
   678 				else
   679 					{
   680 					delete iObjects;
   681 					iObjects=NULL;
   682 					}
   683 				iAllocated=newAlloc;
   684 				}
   685 			if(aLock)
   686 				Unlock();
   687 			anObj->iContainer = NULL;
   688 			return;
   689 			}
   690 		pS++;
   691 		}
   692 	Fault(EObjRemoveObjectNotFound);
   693 	}
   694 
   695 CFsObject *CFsObjectCon::operator[](TInt anIndex)
   696 //
   697 // Return the object at anIndex.
   698 //
   699 	{
   700 	__ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount, Fault(EArrayIndexOutOfRange));
   701 	return iObjects[anIndex];
   702 	}
   703 
   704 CFsObject *CFsObjectCon::At(TInt aFindHandle) const
   705 //
   706 // Return the object at aFindHandle.
   707 // Should only be used there is no other access to the CFsObject
   708 //
   709 	{
   710 
   711 	__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Fault(EObjFindBadHandle));
   712 	TInt ix=index(aFindHandle);
   713 	__ASSERT_ALWAYS(ix<iCount,Fault(EObjFindIndexOutOfRange));
   714 	return iObjects[ix];
   715 	}
   716 
   717 CFsObject *CFsObjectCon::AtL(TInt aFindHandle) const
   718 //
   719 // Return the object at aFindHandle.
   720 // Should only be used if no other access to the CFsObject
   721 //
   722 	{
   723 
   724 	__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,User::Leave(KErrBadHandle));
   725 	TInt ix=index(aFindHandle);
   726 	__ASSERT_ALWAYS(ix<iCount,User::Leave(KErrArgument));
   727 	return iObjects[ix];
   728 	}
   729 
   730 LOCAL_C TInt validateName(const TDesC &aName)
   731 //
   732 // Return KErrBadName if the name is invalid.
   733 //
   734 	{
   735 
   736 	if (aName.Locate('*')!=KErrNotFound || aName.Locate('?')!=KErrNotFound || aName.Locate(':')!=KErrNotFound)
   737 		return(KErrBadName);
   738 	return(KErrNone);
   739 	}
   740 
   741 
   742 TBool CFsObjectCon::NamesMatch(const TName& anObjectName, const CFsObject* aCurrentObject) const
   743 //
   744 // 
   745 //
   746 	{
   747 
   748 	if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same
   749 		return(EFalse);
   750 	return(anObjectName.Compare(*aCurrentObject->iName)==0); // short names are different, therefore not the same
   751 	}
   752 
   753 TInt CFsObjectCon::CheckUniqueName(const CFsObject* anObject) const
   754 //
   755 // Returns KErrBadName if the name is invalid or
   756 // returns KErrAlreadyExists if the full name is not unique.
   757 //
   758 	{
   759 
   760 	TName name(*(anObject->iName));
   761 	TInt r=validateName(name);
   762 	if (r!=KErrNone)
   763 		return r;
   764 
   765 	if (!iCount)
   766 		return KErrNone;
   767 
   768 	CFsObject** pS=iObjects;
   769 	CFsObject** pE=pS+iCount;
   770 
   771 	// if it's name is null, just need to check it's not already there
   772 	if (!anObject->iName)
   773 		{
   774 		do
   775 			{
   776 			if (*pS==anObject)
   777 				return KErrAlreadyExists;
   778 			} while(++pS<pE);
   779 		return KErrNone;
   780 		}
   781 
   782 	do
   783 		{
   784 		if (NamesMatch(name,*pS))
   785 			return KErrAlreadyExists;
   786 		} while(++pS<pE);
   787 	return KErrNone;
   788 	}
   789 
   790 TInt CFsObjectCon::FindByName(TInt &aFindHandle,const TDesC &aMatch) const
   791 //
   792 // Find an object starting at aFindHandle which matches aMatch
   793 // just using the objects name.
   794 //
   795 	{
   796 
   797 	if (!iCount)
   798 		return KErrNotFound;
   799 	TInt ix=0;
   800 	if (aFindHandle!=0)
   801 		{
   802 		__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Fault(EObjFindBadHandle));
   803 		ix=index(aFindHandle)+1;
   804 		};
   805 	CFsObject** pS=iObjects;
   806 	CFsObject** pE=pS+iCount;
   807 	pS+=ix;
   808 	while(pS<pE)
   809 		{
   810 		TName name=*((*pS++)->iName);
   811 		if (name.MatchF(aMatch)!=KErrNotFound)
   812 			{
   813 			aFindHandle=makeFindHandle(ix,iUniqueID);
   814 			return KErrNone;
   815 			}
   816 		ix++;
   817 		}
   818 	aFindHandle=makeFindHandle(KObjectMaxIndex,iUniqueID);
   819 	return KErrNotFound;
   820 	}
   821 
   822 /**
   823 Constructs the object and initializes the Drive number as an invalid drive. 
   824  
   825 Once constructed, a dispatch object cannot be deleted until its reference 
   826 count is reduced to zero. 
   827  
   828 @see CFsDispatchObject::Close
   829 */
   830 CFsDispatchObject::CFsDispatchObject()
   831 	: iDriveNumber(-1) 
   832 	{}
   833 
   834 /**
   835 Initialises dispatch object
   836 
   837 Creates an internal request and sets it as a file resource close operation.
   838 Initialises drive number as specified.
   839 
   840 @param aDrvNumber Drive for which the request is intended.
   841 */
   842 void CFsDispatchObject::DoInitL(TInt aDrvNumber)
   843 	{
   844 	CFsInternalRequest* PR= new(ELeave) CFsInternalRequest;
   845 	__THRD_PRINT1(_L("internal request = 0x%x"),PR);
   846 	PR->Set(DispatchObjectCloseOp,NULL);
   847 	iRequest = PR;
   848 	iRequest->SetDriveNumber(aDrvNumber);
   849 	iRequest->SetScratchValue((TUint)this);
   850 	iDriveNumber=aDrvNumber;
   851 	}
   852 
   853 /**
   854 Closes this dispatch object.
   855 
   856 Decrements the reference count by one. If this becomes zero then the request 
   857 will either call Dispatch() if currently not within the correct thread 
   858 context otherwise the function calls DoClose() on this dispatch object.
   859 
   860 @see CFsDispatchObject::IsCorrectThread
   861      CFsDispatchObject::Dispatch
   862      CFsObject::DoClose
   863 */
   864 EXPORT_C void CFsDispatchObject::Close()
   865 	{
   866 	__THRD_PRINT1(_L("CFsDispatchObject::Close() 0x%x"),this);
   867 	if(Dec()!=1)
   868 		return;
   869 	if(!IsCorrectThread())
   870 		Dispatch();
   871 	else
   872 		DoClose();
   873 	}
   874 
   875 /**
   876 Destructor.
   877  
   878 Deletes assigned CFsRequest object.
   879 */
   880 CFsDispatchObject::~CFsDispatchObject()
   881 	{
   882 	__THRD_PRINT(_L("CFsDispatchObject::~CFsDispatchObject()"));
   883 	if(iRequest)
   884 		delete(iRequest);
   885 	}
   886 
   887 /**
   888 Dispatches an assigned CFsRequest object.
   889 
   890 @see CFsRequest::Dispatch()
   891 */
   892 void CFsDispatchObject::Dispatch()
   893 	{
   894 	__ASSERT_DEBUG(iRequest,Fault(EDispatchObjectDispatch));
   895 	iRequest->Dispatch();
   896 	}
   897 
   898 
   899 /**
   900 Determine if this object is within the correct drive thread context 
   901 for file resource request.
   902 For example subsession close request.
   903 
   904 @return ETrue if within the correct drive thread context.
   905 */
   906 EXPORT_C TBool CFsDispatchObject::IsCorrectThread()
   907 	{
   908 	if(!iRequest)
   909 		return(ETrue);
   910 	FsThreadManager::LockDrive(iRequest->DriveNumber());
   911 	TBool b;
   912 	__ASSERT_ALWAYS(FsThreadManager::IsDriveAvailable(iRequest->DriveNumber(),EFalse) || FsThreadManager::IsMainThread(), Fault(EDispatchObjectThread));
   913 	if(!FsThreadManager::IsDriveAvailable(iRequest->DriveNumber(),EFalse) && FsThreadManager::IsMainThread())
   914 		b=ETrue;
   915 	else if(FsThreadManager::IsDriveSync(iRequest->DriveNumber(),EFalse) && FsThreadManager::IsMainThread())
   916 		b=ETrue;
   917 	else
   918 		b=FsThreadManager::IsDriveThread(iRequest->DriveNumber(),EFalse);
   919 	FsThreadManager::UnlockDrive(iRequest->DriveNumber());
   920 	return(b);
   921 	}
   922 
   923 TInt TFsCloseObject::Initialise(CFsRequest* /*aRequest*/)
   924 //
   925 //
   926 //
   927 	{
   928 	return(KErrNone);
   929 	}
   930 
   931 TInt TFsCloseObject::DoRequestL(CFsRequest* /*aRequest*/)
   932 //
   933 //
   934 //
   935 	{
   936 	__PRINT(_L("TFsCloseObject::DoRequestL()"));
   937 	return(KErrNone);
   938 	}
   939 
   940 TInt TFsCloseObject::Complete(CFsRequest* aRequest)
   941 //
   942 //
   943 //
   944 	{
   945 	__PRINT(_L("TFsCloseObject::Complete()"));
   946 	CFsDispatchObject* pO=(CFsDispatchObject*)aRequest->ScratchValue();
   947 	// set CFsDispatchObject::iRequest to NULL since request will be deleted in Free()
   948 	pO->iRequest=NULL;
   949 	pO->DoClose();
   950 	return(KErrNone);
   951 	}
   952 
   953