mtpfws/mtpfw/src/cmtphandleallocator.cpp
changeset 0 d0791faffa3f
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2006-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 "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 //
       
    15 
       
    16 
       
    17 #include <mtp/mtpprotocolconstants.h>
       
    18 #include "cmtphandleallocator.h"
       
    19 #include "tmtptypeobjecthandle.h"
       
    20 #include "dbutility.h"
       
    21 #include "cmtpobjectstore.h"
       
    22     
       
    23 static const TUint KMTPMinimumId = 0x00000000;
       
    24 static const TUint KMTPMaximumId = 0x00FFFFFE;
       
    25 static const TInt64 KMTPPOUIDStart = -1;
       
    26 static const TInt  KMTPMaxDataProviderGranularity = 8;
       
    27 #if defined(_DEBUG)
       
    28 static const TInt  KMTPMaxDataProviderId = 0x00000100;
       
    29 #endif
       
    30 
       
    31 
       
    32 /**
       
    33 Two-phase object construction
       
    34 */
       
    35 CMTPHandleAllocator* CMTPHandleAllocator::NewL( CMTPObjectStore& aObjectStore )
       
    36 	{
       
    37 	CMTPHandleAllocator* self = new (ELeave) CMTPHandleAllocator(aObjectStore);
       
    38 	CleanupStack::PushL(self);
       
    39 	self->ConstructL();
       
    40 	CleanupStack::Pop(self);
       
    41 	return self;
       
    42 	}
       
    43 	
       
    44 /**
       
    45 destructor
       
    46 */	
       
    47 CMTPHandleAllocator::~CMTPHandleAllocator()
       
    48 	{
       
    49 	iNextIds.Close();
       
    50 	
       
    51     iNextIDPool.ResetAndDestroy();
       
    52 	}
       
    53 
       
    54 /**
       
    55 Get the next object identifier (Handle) for the specified data provider.
       
    56 @param aDataProviderId	The Id of the data provider 
       
    57 @return the next object identifier (Handle)
       
    58 @leave KErrOverFlow	if the object identifier has been exhausted for the data provider
       
    59 */	
       
    60 TUint32 CMTPHandleAllocator::NextIdL(TUint aDataProviderId)
       
    61 	{
       
    62 	__ASSERT_DEBUG(aDataProviderId < KMTPMaxDataProviderId, User::Invariant());
       
    63 	if (aDataProviderId >= iNextIds.Count())
       
    64 	    {
       
    65 	    ExtendArrayL(aDataProviderId);
       
    66 	    }
       
    67 	
       
    68 	TUint result = ++iNextIds[aDataProviderId];
       
    69 	if(result > KMTPMaximumId)
       
    70 		{
       
    71 		--iNextIds[aDataProviderId];
       
    72         result = NextIDFromPoolL(aDataProviderId);
       
    73 		}
       
    74 	
       
    75 	TMTPTypeObjectHandle handle(result,  aDataProviderId);
       
    76 	return handle.Value(); 
       
    77 	}
       
    78 
       
    79 TInt64 CMTPHandleAllocator::NextPOUIDL()
       
    80 {
       
    81 	return ++iNextPOUID;
       
    82 }
       
    83 /**
       
    84 Initialize the allocator for this DP.  This must be called if and only if the
       
    85 DP uses persistent objects, and some persistent objects exist in the object
       
    86 store, so that later allocations do not duplicate earlier object IDs.
       
    87 If it is called, it must therefore be called before any new objects are
       
    88 allocated for this DP.
       
    89 @param aDataProviderId	Id of the data provider 
       
    90 @param aObjectId Object Id of the largest object already allocated,
       
    91 or KMTPHandleNone if no objects have been allocated
       
    92 */
       
    93 
       
    94 void CMTPHandleAllocator::SetIdL( TUint32 aHandleID, TInt64 aPOUID )
       
    95 	{
       
    96 	TUint dpID = TMTPTypeObjectHandle::DataProviderID(aHandleID);
       
    97 	TUint objID = TMTPTypeObjectHandle::ObjectID(aHandleID);
       
    98 
       
    99 	__ASSERT_DEBUG(dpID < KMTPMaxDataProviderId, User::Invariant());
       
   100 	
       
   101 	if ( dpID >= iNextIds.Count())
       
   102 	    {
       
   103 	    ExtendArrayL(dpID);
       
   104 	    }
       
   105 	
       
   106 	if( objID > iNextIds[dpID] )
       
   107 	    {
       
   108 	    iNextIds[dpID] = objID ;
       
   109 	    }
       
   110 	if( aPOUID > iNextPOUID )
       
   111 	    {
       
   112 	    iNextPOUID = aPOUID;
       
   113 	    }
       
   114 	}
       
   115 
       
   116 /**
       
   117 Standard C++ constructor
       
   118 */	
       
   119 CMTPHandleAllocator::CMTPHandleAllocator( CMTPObjectStore& aObjectStore):
       
   120 	iObjectStore(aObjectStore),
       
   121 	iNextIds(KMTPMaxDataProviderGranularity),
       
   122 	iNextPOUID(KMTPPOUIDStart)
       
   123 	{
       
   124 	}
       
   125 
       
   126 /**
       
   127 Extends the array to handle more data providers. DP IDs are allocated
       
   128 sequentially, so this way the array never needs to be much larger
       
   129 than necessary.  This must only be called if the array size needs to be increased.
       
   130 @param aDataProviderId the array must be sized to fit this data provider ID
       
   131 */	
       
   132 void CMTPHandleAllocator::ExtendArrayL(TUint aDataProviderId)
       
   133 	{
       
   134 	__ASSERT_DEBUG(aDataProviderId >= iNextIds.Count(), User::Invariant());
       
   135 	TInt increase = aDataProviderId - iNextIds.Count() + KMTPMaxDataProviderGranularity;
       
   136 	while (increase--)
       
   137 		{
       
   138 		User::LeaveIfError(iNextIds.Append(KMTPMinimumId));
       
   139 		}
       
   140 	}
       
   141 	
       
   142 /**
       
   143 Second-phase construction
       
   144 */	
       
   145 void CMTPHandleAllocator::ConstructL()
       
   146 	{
       
   147 	ExtendArrayL(0);
       
   148 	}
       
   149 
       
   150 TBool CMTPHandleAllocator::AppendHandleBlockL( TUint aDataProviderId, TUint aNextID, TInt aSpace )
       
   151     {
       
   152     TInt index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending );
       
   153     if( index == KErrNotFound )
       
   154         {
       
   155         CDPHandleCache* cache = CDPHandleCache::NewLC(aDataProviderId);
       
   156         iNextIDPool.InsertInOrderL(cache , TLinearOrder<CDPHandleCache>(CDPHandleCache::HanldeCacheOrderFromAscending));
       
   157         CleanupStack::Pop(cache);
       
   158         
       
   159         index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending );
       
   160         }
       
   161     
       
   162     iNextIDPool[index]->AppendL( CDPHandleCache::THandleBlock( TMTPTypeObjectHandle::ObjectID(aNextID), aSpace) );
       
   163     
       
   164     
       
   165     if(iNextIDPool[index]->BlocksCount() < CDPHandleCache::MaxNumOfBlocks() )
       
   166         {
       
   167         return ETrue;
       
   168         }
       
   169     else
       
   170         {
       
   171         return EFalse;
       
   172         }
       
   173     }
       
   174 
       
   175 TUint32 CMTPHandleAllocator::NextIDFromPoolL( TUint aDataProviderId )
       
   176     {
       
   177     TInt index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending );
       
   178     if( index == KErrNotFound )
       
   179         {
       
   180         iObjectStore.CalcFreeHandlesL(aDataProviderId);
       
   181         
       
   182         index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending );
       
   183         if( index == KErrNotFound )
       
   184             {
       
   185             User::Leave(KErrOverflow);
       
   186             }
       
   187         }
       
   188     
       
   189     TUint32 ret = iNextIDPool[index]->NextHandleID();
       
   190     if( !iNextIDPool[index]->HasCache() )
       
   191         {
       
   192         iNextIDPool.Remove(index);
       
   193         }
       
   194     
       
   195     if(ret > KMTPMaximumId )
       
   196         {
       
   197         User::Leave(KErrOverflow);
       
   198         }
       
   199     
       
   200     return ret;
       
   201     }
       
   202 
       
   203 CMTPHandleAllocator::CDPHandleCache::THandleBlock::THandleBlock(TUint aNextID, TInt aSpace):
       
   204     iNextID(aNextID),
       
   205     iSpace(aSpace)
       
   206     {
       
   207     }
       
   208 
       
   209 TInt CMTPHandleAllocator::CDPHandleCache::HanldeCacheOrderFromAscending( const CDPHandleCache& aL, const CDPHandleCache& aR)
       
   210     {
       
   211     return aL.DPID() - aR.DPID();
       
   212     }
       
   213 
       
   214 TInt CMTPHandleAllocator::CDPHandleCache::HanldeCacheOrderFromKeyAscending( const TUint* aL, const CDPHandleCache& aR)
       
   215     {
       
   216     return (*aL) - aR.DPID();
       
   217     }
       
   218 
       
   219 CMTPHandleAllocator::CDPHandleCache::CDPHandleCache(TUint aDataProviderId ):
       
   220     iDPID(aDataProviderId)
       
   221     {
       
   222     }
       
   223 
       
   224 CMTPHandleAllocator::CDPHandleCache::~CDPHandleCache()
       
   225     {
       
   226     iBlocks.Close();
       
   227     }
       
   228 
       
   229 void CMTPHandleAllocator::CDPHandleCache::ConstructL()
       
   230     {
       
   231     }
       
   232 
       
   233 CMTPHandleAllocator::CDPHandleCache* CMTPHandleAllocator::CDPHandleCache::NewLC( TUint aDataProviderId )
       
   234     {
       
   235     CDPHandleCache* self = new (ELeave) CDPHandleCache(aDataProviderId);
       
   236     CleanupStack::PushL(self);
       
   237     self->ConstructL();
       
   238     return self;
       
   239     }
       
   240 
       
   241 TUint32 CMTPHandleAllocator::CDPHandleCache::NextHandleID()
       
   242     {
       
   243     TUint32 ret = KMTPMaximumId + 1;
       
   244     if(iBlocks.Count() == 0)
       
   245         {
       
   246         return ret;
       
   247         }
       
   248     
       
   249     ret = iBlocks[0].iNextID;
       
   250     --iBlocks[0].iSpace;
       
   251     
       
   252     if( 0 == iBlocks[0].iSpace )
       
   253         {
       
   254         iBlocks.Remove(0);
       
   255         }
       
   256     else
       
   257         {
       
   258         iBlocks[0].iNextID++;
       
   259         }
       
   260     
       
   261     return ret;
       
   262     }
       
   263 
       
   264 void CMTPHandleAllocator::CDPHandleCache::AppendL( const THandleBlock& aBlock )
       
   265     {
       
   266     iBlocks.AppendL( aBlock );
       
   267     }