mtpfws/mtpfw/src/cmtphandleallocator.cpp
changeset 0 d0791faffa3f
child 47 63cf70d3ecd8
--- /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 <mtp/mtpprotocolconstants.h>
+#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>(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 );
+    }