diff -r 000000000000 -r d0791faffa3f mtpfws/mtpfw/src/cmtphandleallocator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mtpfws/mtpfw/src/cmtphandleallocator.cpp Tue Feb 02 01:11:40 2010 +0200 @@ -0,0 +1,267 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + + +#include +#include "cmtphandleallocator.h" +#include "tmtptypeobjecthandle.h" +#include "dbutility.h" +#include "cmtpobjectstore.h" + +static const TUint KMTPMinimumId = 0x00000000; +static const TUint KMTPMaximumId = 0x00FFFFFE; +static const TInt64 KMTPPOUIDStart = -1; +static const TInt KMTPMaxDataProviderGranularity = 8; +#if defined(_DEBUG) +static const TInt KMTPMaxDataProviderId = 0x00000100; +#endif + + +/** +Two-phase object construction +*/ +CMTPHandleAllocator* CMTPHandleAllocator::NewL( CMTPObjectStore& aObjectStore ) + { + CMTPHandleAllocator* self = new (ELeave) CMTPHandleAllocator(aObjectStore); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +/** +destructor +*/ +CMTPHandleAllocator::~CMTPHandleAllocator() + { + iNextIds.Close(); + + iNextIDPool.ResetAndDestroy(); + } + +/** +Get the next object identifier (Handle) for the specified data provider. +@param aDataProviderId The Id of the data provider +@return the next object identifier (Handle) +@leave KErrOverFlow if the object identifier has been exhausted for the data provider +*/ +TUint32 CMTPHandleAllocator::NextIdL(TUint aDataProviderId) + { + __ASSERT_DEBUG(aDataProviderId < KMTPMaxDataProviderId, User::Invariant()); + if (aDataProviderId >= iNextIds.Count()) + { + ExtendArrayL(aDataProviderId); + } + + TUint result = ++iNextIds[aDataProviderId]; + if(result > KMTPMaximumId) + { + --iNextIds[aDataProviderId]; + result = NextIDFromPoolL(aDataProviderId); + } + + TMTPTypeObjectHandle handle(result, aDataProviderId); + return handle.Value(); + } + +TInt64 CMTPHandleAllocator::NextPOUIDL() +{ + return ++iNextPOUID; +} +/** +Initialize the allocator for this DP. This must be called if and only if the +DP uses persistent objects, and some persistent objects exist in the object +store, so that later allocations do not duplicate earlier object IDs. +If it is called, it must therefore be called before any new objects are +allocated for this DP. +@param aDataProviderId Id of the data provider +@param aObjectId Object Id of the largest object already allocated, +or KMTPHandleNone if no objects have been allocated +*/ + +void CMTPHandleAllocator::SetIdL( TUint32 aHandleID, TInt64 aPOUID ) + { + TUint dpID = TMTPTypeObjectHandle::DataProviderID(aHandleID); + TUint objID = TMTPTypeObjectHandle::ObjectID(aHandleID); + + __ASSERT_DEBUG(dpID < KMTPMaxDataProviderId, User::Invariant()); + + if ( dpID >= iNextIds.Count()) + { + ExtendArrayL(dpID); + } + + if( objID > iNextIds[dpID] ) + { + iNextIds[dpID] = objID ; + } + if( aPOUID > iNextPOUID ) + { + iNextPOUID = aPOUID; + } + } + +/** +Standard C++ constructor +*/ +CMTPHandleAllocator::CMTPHandleAllocator( CMTPObjectStore& aObjectStore): + iObjectStore(aObjectStore), + iNextIds(KMTPMaxDataProviderGranularity), + iNextPOUID(KMTPPOUIDStart) + { + } + +/** +Extends the array to handle more data providers. DP IDs are allocated +sequentially, so this way the array never needs to be much larger +than necessary. This must only be called if the array size needs to be increased. +@param aDataProviderId the array must be sized to fit this data provider ID +*/ +void CMTPHandleAllocator::ExtendArrayL(TUint aDataProviderId) + { + __ASSERT_DEBUG(aDataProviderId >= iNextIds.Count(), User::Invariant()); + TInt increase = aDataProviderId - iNextIds.Count() + KMTPMaxDataProviderGranularity; + while (increase--) + { + User::LeaveIfError(iNextIds.Append(KMTPMinimumId)); + } + } + +/** +Second-phase construction +*/ +void CMTPHandleAllocator::ConstructL() + { + ExtendArrayL(0); + } + +TBool CMTPHandleAllocator::AppendHandleBlockL( TUint aDataProviderId, TUint aNextID, TInt aSpace ) + { + TInt index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending ); + if( index == KErrNotFound ) + { + CDPHandleCache* cache = CDPHandleCache::NewLC(aDataProviderId); + iNextIDPool.InsertInOrderL(cache , TLinearOrder(CDPHandleCache::HanldeCacheOrderFromAscending)); + CleanupStack::Pop(cache); + + index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending ); + } + + iNextIDPool[index]->AppendL( CDPHandleCache::THandleBlock( TMTPTypeObjectHandle::ObjectID(aNextID), aSpace) ); + + + if(iNextIDPool[index]->BlocksCount() < CDPHandleCache::MaxNumOfBlocks() ) + { + return ETrue; + } + else + { + return EFalse; + } + } + +TUint32 CMTPHandleAllocator::NextIDFromPoolL( TUint aDataProviderId ) + { + TInt index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending ); + if( index == KErrNotFound ) + { + iObjectStore.CalcFreeHandlesL(aDataProviderId); + + index = iNextIDPool.FindInOrder( aDataProviderId, CDPHandleCache::HanldeCacheOrderFromKeyAscending ); + if( index == KErrNotFound ) + { + User::Leave(KErrOverflow); + } + } + + TUint32 ret = iNextIDPool[index]->NextHandleID(); + if( !iNextIDPool[index]->HasCache() ) + { + iNextIDPool.Remove(index); + } + + if(ret > KMTPMaximumId ) + { + User::Leave(KErrOverflow); + } + + return ret; + } + +CMTPHandleAllocator::CDPHandleCache::THandleBlock::THandleBlock(TUint aNextID, TInt aSpace): + iNextID(aNextID), + iSpace(aSpace) + { + } + +TInt CMTPHandleAllocator::CDPHandleCache::HanldeCacheOrderFromAscending( const CDPHandleCache& aL, const CDPHandleCache& aR) + { + return aL.DPID() - aR.DPID(); + } + +TInt CMTPHandleAllocator::CDPHandleCache::HanldeCacheOrderFromKeyAscending( const TUint* aL, const CDPHandleCache& aR) + { + return (*aL) - aR.DPID(); + } + +CMTPHandleAllocator::CDPHandleCache::CDPHandleCache(TUint aDataProviderId ): + iDPID(aDataProviderId) + { + } + +CMTPHandleAllocator::CDPHandleCache::~CDPHandleCache() + { + iBlocks.Close(); + } + +void CMTPHandleAllocator::CDPHandleCache::ConstructL() + { + } + +CMTPHandleAllocator::CDPHandleCache* CMTPHandleAllocator::CDPHandleCache::NewLC( TUint aDataProviderId ) + { + CDPHandleCache* self = new (ELeave) CDPHandleCache(aDataProviderId); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +TUint32 CMTPHandleAllocator::CDPHandleCache::NextHandleID() + { + TUint32 ret = KMTPMaximumId + 1; + if(iBlocks.Count() == 0) + { + return ret; + } + + ret = iBlocks[0].iNextID; + --iBlocks[0].iSpace; + + if( 0 == iBlocks[0].iSpace ) + { + iBlocks.Remove(0); + } + else + { + iBlocks[0].iNextID++; + } + + return ret; + } + +void CMTPHandleAllocator::CDPHandleCache::AppendL( const THandleBlock& aBlock ) + { + iBlocks.AppendL( aBlock ); + }