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