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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfile\sf_obj.cpp
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;
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));}
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));}
45 CFsObjectConIx* CFsObjectConIx::NewL()
47 // Create an instance of this class.
51 return new(ELeave) CFsObjectConIx;
54 CFsObjectConIx::CFsObjectConIx()
62 CFsObjectConIx::~CFsObjectConIx()
72 CFsObjectCon* pS=iContainers[i];
79 void CFsObjectConIx::CreateContainerL(CFsObjectCon*& aContainer)
81 // Actually create the container
85 aContainer=CFsObjectCon::NewL();
86 aContainer->iUniqueID=iNextUniqueID;
87 if (iCount==iAllocated)
89 TInt newAlloc=iAllocated+KObjectConIxGranularity;
90 iContainers=(CFsObjectCon**)User::ReAllocL(iContainers, newAlloc*sizeof(CFsObjectCon*));
93 iContainers[iCount++]=aContainer;
96 CFsObjectCon* CFsObjectConIx::CreateL()
98 // Create a new container.
102 CFsObjectCon* pC=NULL;
103 TRAPD(r,CreateContainerL(pC))
113 void CFsObjectConIx::Remove(CFsObjectCon* aCon)
115 // Remove a container from the index.
120 CFsObjectCon** pS=iContainers;
121 CFsObjectCon** pE=pS+iCount;
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)
132 iContainers=(CFsObjectCon**)User::ReAlloc(iContainers,newAlloc*sizeof(CFsObjectCon*));
145 Fault(EObjRemoveContainerNotFound);
150 Constructs the object and initializes the reference count to one.
152 Once constructed, a reference counting object cannot be deleted until its
153 reference count is reduced to zero.
155 @see CFsObject::Close
157 EXPORT_C CFsObject::CFsObject()
169 Deallocates memory associated with this objects name, if a name
172 @panic FSERV 104 if the reference count is not zero when
173 the destructor is called.
175 EXPORT_C CFsObject::~CFsObject()
177 __PRINT1(_L("CFsObject::~CFsObject() 0x%x"),this);
178 __ASSERT_ALWAYS(Dec()==0,Fault(EObjDestructorAccessCount));
179 __ASSERT_ALWAYS(!iContainer,Fault(EObjDestructorContainer));
186 Opens this reference counting object.
188 The default behaviour increments the reference count by one.
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.
194 @return KErrNone, or another system-wide error code.
197 EXPORT_C TInt CFsObject::Open()
201 __THRD_PRINT2(_L("CFsObject::Open() object=0x%x count=%d"),this,count);
202 __ASSERT_DEBUG(count>=1,Fault(EFsObjectOpen));
208 Removes an assigned container object then deletes this reference
211 void CFsObject::DoClose()
213 __THRD_PRINT(_L("CFsObject::DoClose()"));
216 iContainer->Remove(this,ETrue);
224 Closes this reference counting object.
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.
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
233 @see CFsObject::DoClose
235 EXPORT_C void CFsObject::Close()
237 __THRD_PRINT(_L("CFsObject::Close()"));
244 Determine if this object is within the correct drive thread context
245 for file based operations.
247 The default behaviour is to return True.
249 A derived class implementation is required.
253 EXPORT_C TBool CFsObject::IsCorrectThread()
261 Sets or clears this reference counting object's name.
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
267 To clear an existing name, specify a NULL argument.
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.
272 @return KErrNone if the function is successful;
273 KErrNoMemory if there is insufficient memory available.
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.
280 EXPORT_C TInt CFsObject::SetName(const TDesC *aName)
286 iName=aName->Alloc();
288 return(KErrNoMemory);
295 Gets the name of this reference counting object.
297 The default behaviour provided by this function depends on whether a name
298 has been explicitly set into the object:
300 If a name has previously been set, then the function returns that name.
302 If a name has not been set, then the function returns NULL.
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.
307 EXPORT_C TName CFsObject::Name() const
318 Gets the Unique ID of the assigned object container to this object.
320 @return A unique number for file system container objects.
322 TInt CFsObject::UniqueID() const {return(iContainer->UniqueID());}
325 CFsObjectIx* CFsObjectIx::NewL()
327 // Create an instance of this class.
330 CFsObjectIx* pO=new(ELeave) CFsObjectIx;
331 TInt r=pO->iLock.CreateLocal();
340 CFsObjectIx::CFsObjectIx()
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.
358 void CFsObjectIx::CloseMainThreadObjects()
360 __ASSERT_DEBUG(FsThreadManager::IsMainThread(),Fault(EObjectIxMainThread));
361 __PRINT(_L("CFsObjectIx::CloseThreadObjects()"));
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.
369 while(++i<iHighWaterMark)
371 SFsObjectIxRec* pS=iObjects+i;
372 CFsObject *pO=pS->obj;
373 if (pO && pO->IsCorrectThread())
375 // invalidate entry before closing it
384 CFsObjectIx::~CFsObjectIx()
387 // Assumes that no need to lock
390 __PRINT1(_L("CFsObjectIx::~CFsObjectIx() 0x%x"),this);
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.
397 while(++i<iHighWaterMark)
399 SFsObjectIxRec* pS=iObjects+i;
400 CFsObject *pO=pS->obj;
403 // invalidate entry before closing it
412 TInt CFsObjectIx::AddL(CFsObject* anObj,TBool aLock)
414 // Add a new object to the index.
419 SFsObjectIxRec *pS=iObjects;
420 SFsObjectIxRec *pE=pS+iHighWaterMark;
423 while(pS<pE && pS->obj)
427 if (pS==pE && iAllocated==iHighWaterMark)
429 // no slots free, so reallocate array
430 if (iHighWaterMark==KObjectIxMaxHandles)
434 User::LeaveNoMemory();
436 TInt newAlloc=iAllocated + KObjectIxGranularity;
437 SFsObjectIxRec* pA=(SFsObjectIxRec*)User::ReAlloc(iObjects, newAlloc*sizeof(SFsObjectIxRec));
442 User::Leave(KErrNoMemory);
450 pS->uniqueID=(TUint16)anObj->UniqueID();
451 pS->instance=(TUint16)instanceLimit(iNextInstance);
455 TInt h=makeHandle(i,pS->instance);
461 void CFsObjectIx::Remove(TInt aHandle,TBool aLock)
463 // Remove an object from the index.
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);
476 if (i==iHighWaterMark-1)
482 } while(i>=0 && !pR->obj);
483 TInt newAlloc=(i+KObjectIxGranularity)&~(KObjectIxGranularity-1);
484 if (newAlloc!=iAllocated)
487 iObjects=(SFsObjectIxRec*)User::ReAlloc(iObjects,newAlloc*sizeof(SFsObjectIxRec));
502 CFsObject *CFsObjectIx::At(TInt aHandle,TInt aUniqueID,TBool aLock)
504 // Return the object from its handle.
509 TInt i=index(aHandle);
510 if (i>=iHighWaterMark)
516 SFsObjectIxRec *pS=iObjects+i;
517 if (pS->instance!=instance(aHandle) || pS->uniqueID!=aUniqueID)
528 CFsObject *CFsObjectIx::At(TInt aHandle,TBool aLock)
530 // Return the object from its handle.
535 TInt i=index(aHandle);
536 if (i>=iHighWaterMark)
542 SFsObjectIxRec *pS=iObjects+i;
543 if (pS->instance!=instance(aHandle))
554 TInt CFsObjectIx::At(const CFsObject* anObj,TBool aLock)
556 // Return the handle from an object.
563 SFsObjectIxRec* pS=iObjects;
564 SFsObjectIxRec* pE=pS+iHighWaterMark;
566 while(pS<pE && pS->obj!=anObj)
570 TInt h=makeHandle(i,pS->instance);
582 CFsObject* CFsObjectIx::operator[](TInt anIndex)
584 // Return the object at anIndex
588 __ASSERT_ALWAYS(anIndex>=0 && anIndex<iHighWaterMark,Fault(EArrayIndexOutOfRange));
589 return iObjects[anIndex].obj;
592 CFsObjectCon* CFsObjectCon::NewL()
594 // Create a new instance of this class.
597 CFsObjectCon* pO=new(ELeave) CFsObjectCon(ENotOwnerID);
598 TInt r=pO->iLock.CreateLocal();
607 CFsObjectCon::CFsObjectCon(TInt aUniqueID)
611 : iUniqueID(aUniqueID)
618 CFsObjectCon::~CFsObjectCon()
623 __ASSERT_ALWAYS(iCount==0,Fault(EObjectConDestructor));
628 void CFsObjectCon::AddL(CFsObject* anObj,TBool aLock)
630 // Install a new object to the container. The full name must be unique.
634 User::LeaveIfError(CheckUniqueName(anObj));
637 if (iCount==iAllocated)
639 TInt newAlloc=iAllocated+KObjectConGranularity;
640 CFsObject** pO=(CFsObject**)User::ReAlloc(iObjects, newAlloc*sizeof(CFsObject*));
645 User::Leave(KErrNoMemory);
650 iObjects[iCount++]=anObj;
651 if (iUniqueID!=ENotOwnerID)
652 anObj->iContainer=this;
657 void CFsObjectCon::Remove(CFsObject *anObj,TBool aLock)
659 // Remove an object from the container.
660 // This assumes that close is called by the calling function
665 CFsObject** pS=iObjects;
666 CFsObject** pE=pS+iCount;
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)
677 iObjects=(CFsObject**)User::ReAlloc(iObjects,newAlloc*sizeof(CFsObject*));
687 anObj->iContainer = NULL;
692 Fault(EObjRemoveObjectNotFound);
695 CFsObject *CFsObjectCon::operator[](TInt anIndex)
697 // Return the object at anIndex.
700 __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount, Fault(EArrayIndexOutOfRange));
701 return iObjects[anIndex];
704 CFsObject *CFsObjectCon::At(TInt aFindHandle) const
706 // Return the object at aFindHandle.
707 // Should only be used there is no other access to the CFsObject
711 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Fault(EObjFindBadHandle));
712 TInt ix=index(aFindHandle);
713 __ASSERT_ALWAYS(ix<iCount,Fault(EObjFindIndexOutOfRange));
717 CFsObject *CFsObjectCon::AtL(TInt aFindHandle) const
719 // Return the object at aFindHandle.
720 // Should only be used if no other access to the CFsObject
724 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,User::Leave(KErrBadHandle));
725 TInt ix=index(aFindHandle);
726 __ASSERT_ALWAYS(ix<iCount,User::Leave(KErrArgument));
730 LOCAL_C TInt validateName(const TDesC &aName)
732 // Return KErrBadName if the name is invalid.
736 if (aName.Locate('*')!=KErrNotFound || aName.Locate('?')!=KErrNotFound || aName.Locate(':')!=KErrNotFound)
742 TBool CFsObjectCon::NamesMatch(const TName& anObjectName, const CFsObject* aCurrentObject) const
748 if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same
750 return(anObjectName.Compare(*aCurrentObject->iName)==0); // short names are different, therefore not the same
753 TInt CFsObjectCon::CheckUniqueName(const CFsObject* anObject) const
755 // Returns KErrBadName if the name is invalid or
756 // returns KErrAlreadyExists if the full name is not unique.
760 TName name(*(anObject->iName));
761 TInt r=validateName(name);
768 CFsObject** pS=iObjects;
769 CFsObject** pE=pS+iCount;
771 // if it's name is null, just need to check it's not already there
772 if (!anObject->iName)
777 return KErrAlreadyExists;
784 if (NamesMatch(name,*pS))
785 return KErrAlreadyExists;
790 TInt CFsObjectCon::FindByName(TInt &aFindHandle,const TDesC &aMatch) const
792 // Find an object starting at aFindHandle which matches aMatch
793 // just using the objects name.
802 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Fault(EObjFindBadHandle));
803 ix=index(aFindHandle)+1;
805 CFsObject** pS=iObjects;
806 CFsObject** pE=pS+iCount;
810 TName name=*((*pS++)->iName);
811 if (name.MatchF(aMatch)!=KErrNotFound)
813 aFindHandle=makeFindHandle(ix,iUniqueID);
818 aFindHandle=makeFindHandle(KObjectMaxIndex,iUniqueID);
823 Constructs the object and initializes the Drive number as an invalid drive.
825 Once constructed, a dispatch object cannot be deleted until its reference
826 count is reduced to zero.
828 @see CFsDispatchObject::Close
830 CFsDispatchObject::CFsDispatchObject()
835 Initialises dispatch object
837 Creates an internal request and sets it as a file resource close operation.
838 Initialises drive number as specified.
840 @param aDrvNumber Drive for which the request is intended.
842 void CFsDispatchObject::DoInitL(TInt aDrvNumber)
844 CFsInternalRequest* PR= new(ELeave) CFsInternalRequest;
845 __THRD_PRINT1(_L("internal request = 0x%x"),PR);
846 PR->Set(DispatchObjectCloseOp,NULL);
848 iRequest->SetDriveNumber(aDrvNumber);
849 iRequest->SetScratchValue((TUint)this);
850 iDriveNumber=aDrvNumber;
854 Closes this dispatch object.
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.
860 @see CFsDispatchObject::IsCorrectThread
861 CFsDispatchObject::Dispatch
864 EXPORT_C void CFsDispatchObject::Close()
866 __THRD_PRINT1(_L("CFsDispatchObject::Close() 0x%x"),this);
869 if(!IsCorrectThread())
878 Deletes assigned CFsRequest object.
880 CFsDispatchObject::~CFsDispatchObject()
882 __THRD_PRINT(_L("CFsDispatchObject::~CFsDispatchObject()"));
888 Dispatches an assigned CFsRequest object.
890 @see CFsRequest::Dispatch()
892 void CFsDispatchObject::Dispatch()
894 __ASSERT_DEBUG(iRequest,Fault(EDispatchObjectDispatch));
895 iRequest->Dispatch();
900 Determine if this object is within the correct drive thread context
901 for file resource request.
902 For example subsession close request.
904 @return ETrue if within the correct drive thread context.
906 EXPORT_C TBool CFsDispatchObject::IsCorrectThread()
910 FsThreadManager::LockDrive(iRequest->DriveNumber());
912 __ASSERT_ALWAYS(FsThreadManager::IsDriveAvailable(iRequest->DriveNumber(),EFalse) || FsThreadManager::IsMainThread(), Fault(EDispatchObjectThread));
913 if(!FsThreadManager::IsDriveAvailable(iRequest->DriveNumber(),EFalse) && FsThreadManager::IsMainThread())
915 else if(FsThreadManager::IsDriveSync(iRequest->DriveNumber(),EFalse) && FsThreadManager::IsMainThread())
918 b=FsThreadManager::IsDriveThread(iRequest->DriveNumber(),EFalse);
919 FsThreadManager::UnlockDrive(iRequest->DriveNumber());
923 TInt TFsCloseObject::Initialise(CFsRequest* /*aRequest*/)
931 TInt TFsCloseObject::DoRequestL(CFsRequest* /*aRequest*/)
936 __PRINT(_L("TFsCloseObject::DoRequestL()"));
940 TInt TFsCloseObject::Complete(CFsRequest* aRequest)
945 __PRINT(_L("TFsCloseObject::Complete()"));
946 CFsDispatchObject* pO=(CFsDispatchObject*)aRequest->ScratchValue();
947 // set CFsDispatchObject::iRequest to NULL since request will be deleted in Free()