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