mtpfws/mtpfw/src/cmtpreferencemgr.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 21 Jun 2010 16:36:59 +0300
branchRCL_3
changeset 15 f85613f12947
parent 0 d0791faffa3f
permissions -rw-r--r--
Revision: 201020 Kit: 2010125

// 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/cmtptypearray.h>
#include <mtp/mtpdatatypeconstants.h>
#include <mtp/mtpprotocolconstants.h>
#include <mtp/mtptypessimple.h>

#include "cmtpobjectstore.h"
#include "cmtpreferencemgr.h"
#include "dbutility.h"


_LIT(KSQLReferenceTableName, "ReferenceStore");
_LIT(KSQLReferenceIndexName, "ReferenceIndex");
_LIT(KSQLCreateReferenceTableText,"CREATE TABLE ReferenceStore (HandleId UNSIGNED INTEGER, References LONG VARBINARY)");
_LIT(KSQLCreateReferenceIndexText,"CREATE UNIQUE INDEX ReferenceIndex on ReferenceStore (HandleId)");	


static const TInt KMTPReferenceGranularity = 5;
// Maximum value to use for granularity 
// This will result in 4KB of memory used (1024 * 4bytes) for reference SUID array
static const TInt KMTPMaxGranularity = 1024;

/**
Two phase construction
@param aObjectMgr	Reference to the object manager
@return a pointer to the reference manager instance
*/
CMTPReferenceMgr* CMTPReferenceMgr::NewL(CMTPObjectStore& aObjectStore)
	{
	CMTPReferenceMgr* self = new (ELeave) CMTPReferenceMgr(aObjectStore);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

/**
Destructor
*/	
CMTPReferenceMgr::~CMTPReferenceMgr()
	{
	iBatched.Close();
	}

/**
Provides an MTP array of the target object handles which are referenced 
by the specified source object handle. A pointer to the MTP array is 
placed on the cleanup stack.
@param aFromHandle The MTP object handle of the source object from which 
the references originate.
@return The MTP reference target object handle array. Ownership IS transferred.
@leave One of the system wide error codes, if a processing failure occurs.
*/	
CMTPTypeArray* CMTPReferenceMgr::ReferencesLC(const TMTPTypeUint32& aFromHandle) const
	{
	return GetReferencesLC(aFromHandle.Value());
	}

/**
Provides an SUID array of the target object SUIDs which are referenced by 
the specified source object SUID. A pointer to the SUID array is 
placed on the cleanup stack.
@param aFromSuid The SUID of the source object from which the references 
originate.
@return The reference target object SUID array. Ownership IS transferred.
@leave One of the system wide error codes, if a processing failure occurs.
*/	
CDesCArray* CMTPReferenceMgr::ReferencesLC(const TDesC& aParentSuid) const
	{
	TUint32 handle =  iObjectStore.HandleL(aParentSuid);
	return GetReferencesInDesLC(handle);
	}

/**
Removes all object reference links in which the specified SUID represents 
either the source or target reference object.
@param aSuid The object SUID.
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::RemoveReferencesL(const TDesC& aSuid)
	{
	TUint32 handle =  iObjectStore.HandleL(aSuid);
	RemoveReferencesL(handle);
	}

/**
Creates an abstract reference linkage between the specified source and 
target object SUIDs.
@param aFromSuid The SUID of the source object from which the reference 
originates.
param aToSuid The SUID of the target object to which the reference is 
made.
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::SetReferenceL(const TDesC& aFromSuid, const TDesC& aToSuid)
	{
	TUint32 fromHandle =  iObjectStore.HandleL(aFromSuid);
	TUint32 toHandle =  iObjectStore.HandleL(aToSuid);
	SetReferenceL(fromHandle, toHandle);
	}

/**
Replaces the abstract reference links originating from the specified 
source object handle with the specified set of target object SUIDs.
@param aFromHandle The SUID of the source object from which the references 
originate.
@param aToSuids The reference target MTP object SUID array.
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::SetReferencesL(const TDesC& aParentSuid, const CDesCArray& aToSuids)
	{
	TInt count = aToSuids.Count();
	
	if (count > 0)
		{
		TUint32 fromHandle =  iObjectStore.HandleL(aParentSuid);
	
		// Limit granularity to something less or equal to KMTPMaxGranularity items
		RArray<TUint> toHandles(Min(count, KMTPMaxGranularity));
		CleanupClosePushL(toHandles);
		
		for(TInt i = 0; i < count; i++)
			{
			TUint32 toHandle =  iObjectStore.HandleL(aToSuids[i]);
			toHandles.AppendL(toHandle);
			}	
		
		SetReferencesL(fromHandle, toHandles);	
		CleanupStack::PopAndDestroy(&toHandles);
		}
	}


/**
Constructor/.
*/    
CMTPReferenceMgr::CMTPReferenceMgr(CMTPObjectStore& aObjectStore):
	iObjectStore(aObjectStore)
	{
	
	}

/**
second-phase construction
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::ConstructL()
	{
    iDatabase   = &iObjectStore.Database();

	if(!DBUtility::IsTableExistsL(*iDatabase, KSQLReferenceTableName))
		{
		CreateTableL();
		}
	if(!DBUtility::IsIndexExistsL(*iDatabase, KSQLReferenceTableName, KSQLReferenceIndexName))
		{
		CreateIndexL();
		}
	iBatched.Open(*iDatabase, KSQLReferenceTableName, RDbRowSet::EUpdatable);
	iBatched.SetIndex( KSQLReferenceIndexName ); 
	}

/**
Create the reference table in the database
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::CreateTableL()
	{
	User::LeaveIfError(iDatabase->Execute(KSQLCreateReferenceTableText));	
	}

/**
Create the index in the reference table
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::CreateIndexL()
	{
	User::LeaveIfError(iDatabase->Execute(KSQLCreateReferenceIndexText));	
	}

/**
Get reference on the object identified by aIdentifier
@param aIdentifier	The 64bit internal object identifier
@return The array containing the handles of the references
@leave One of the system wide error codes, if a processing failure occurs.
*/
CMTPTypeArray* CMTPReferenceMgr::GetReferencesLC(TUint aHandle) const
	{
	RArray<TUint> toHandles;
	CleanupClosePushL(toHandles);
	GetReferencesL(aHandle, toHandles);
	
	CMTPTypeArray* mtpReferenceArray = CMTPTypeArray::NewLC(EMTPTypeAUINT32);	
	mtpReferenceArray->AppendL(toHandles);
	CleanupStack::Pop(mtpReferenceArray);
	CleanupStack::PopAndDestroy(&toHandles);
	CleanupStack::PushL(mtpReferenceArray);
	return mtpReferenceArray;
	}

/**
Get reference on the object identified by aIdentifier
@param aIdentifier	The 64bit internal object identifier
@return The array containing the suids of the references
@leave One of the system wide error codes, if a processing failure occurs.
*/	
CDesCArray*	 CMTPReferenceMgr::GetReferencesInDesLC(TUint aHandle) const
	{
	RArray<TUint> toHandles(KMTPReferenceGranularity);
	CleanupClosePushL(toHandles);
	GetReferencesL(aHandle, toHandles);	
	const TInt count = toHandles.Count();
	CDesCArray* mtpReferenceArray = new (ELeave) CDesCArrayFlat((count==0) ? 1 : count);
	CleanupStack::PushL(mtpReferenceArray);
	
	for(TInt i = 0; i < count; i++)
		{
		const TDesC& suid = iObjectStore.ObjectSuidL(toHandles[i]);
		if(suid.Length())
			{
			mtpReferenceArray->AppendL(suid);
			}
		}
	CleanupStack::Pop(mtpReferenceArray);
	CleanupStack::PopAndDestroy(&toHandles);
	CleanupStack::PushL(mtpReferenceArray);
	return mtpReferenceArray;		
	
	}

/**
Get references on the object identified by aIdentifier
@param aIdentifier	The 64bit internal object identifier
@param aReferences	The reference array, on return, containing the 64bit internal identifiers of the references
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::GetReferencesL(TUint aHandle, RArray<TUint>& aToHandles) const
	{
	TUint32 temp = 0;
	TBool   needToUpdate = EFalse;
	aToHandles.Reset();
	if(iBatched.SeekL(aHandle))
		{
		iBatched.GetL();
	    RDbColReadStream readStream;     
        readStream.OpenLC(iBatched,2);
        TInt count = readStream.ReadInt32L();
        while(count--)
        	{
        	temp = readStream.ReadUint32L();
			if(iObjectStore.ObjectExistsL(temp))
	        	aToHandles.AppendL(temp);
			else
				needToUpdate = ETrue;
        	}
        CleanupStack::PopAndDestroy(&readStream);

		
		if(needToUpdate)
			{//Something has been deleted. Write it back to Reference list
			iBatched.UpdateL();
			RDbColWriteStream writeStream;	   
			writeStream.OpenLC(iBatched,2);
			
			count = aToHandles.Count();
			writeStream.WriteInt32L(count);
			for(TInt i = 0; i < count; i++)
				{
				writeStream.WriteUint32L(aToHandles[i]);
				}
			writeStream.CommitL(); 
			CleanupStack::PopAndDestroy(&writeStream);
			iBatched.PutL();			
			}
		
		}	
	return;

	}


/**
Remove reference on the object identified by aIdentifier
@param aIdentifier	The 64bit internal object identifier
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::RemoveReferencesL(TUint aHandle)
	{
	if(iBatched.SeekL(aHandle))
		{
		iBatched.DeleteL();
		IncTranOpsNumL();
		}
	}
/**
Set reference on the object identified by aFromIdentifier
@param aFromIdentifier	The 64bit internal object identifier of the source object
@param aToIdentifier	The 64bit internal object identifier of the referenced object
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::SetReferenceL(TUint aFromHandle, TUint aToHandle)
	{
	RArray<TUint> aToHandleArray(1);
	CleanupClosePushL(aToHandleArray);
	aToHandleArray.AppendL(aToHandle);
	SetReferencesL(aFromHandle, aToHandleArray);
	CleanupStack::PopAndDestroy(&aToHandleArray);
	}

/**
Replaces the abstract reference links originating from the specified 
source object handle with the specified set of target object handles.
@param aFromHandle The handle of the source object from which the references 
originate.
@param aToHandles The reference target object handle array.
@leave One of the system wide error codes, if a processing failure occurs.
*/	
void CMTPReferenceMgr::SetReferencesL(const TMTPTypeUint32& aFromHandle, const CMTPTypeArray& aToHandles)
{
	RArray<TUint> tempArray;
	CleanupClosePushL(tempArray);
	TInt count = aToHandles.NumElements();
	for(TInt i = 0; i < count; i++)
		{
		tempArray.AppendL(aToHandles.ElementUint(i));
		}	
	SetReferencesL(aFromHandle.Value(), tempArray);
	CleanupStack::PopAndDestroy(&tempArray);
}



/**
Set references on the object identified by aFromIdentifier
@param aFromIdentifier	The 64bit internal object identifier of the source object
@param aToIdentifiers	The 64bit internal object identifiers of the referenced objects
@leave One of the system wide error codes, if a processing failure occurs.
*/   	
void CMTPReferenceMgr::SetReferencesL(TUint aHandle, const RArray<TUint>& aToHandles)
	{
	if(iBatched.SeekL(aHandle))
		{
		iBatched.UpdateL();		
		}
	else
		{
		iBatched.InsertL();		
		}
	
	iBatched.SetColL(1, aHandle);
	
	RDbColWriteStream writeStream;     
    writeStream.OpenLC(iBatched,2);
    
    const TInt count = aToHandles.Count();
    writeStream.WriteInt32L(count);
    for(TInt i = 0; i < count; i++)
        {
        writeStream.WriteUint32L(aToHandles[i]);
        }
    writeStream.CommitL(); 
    CleanupStack::PopAndDestroy(&writeStream);
	iBatched.PutL();			
	IncTranOpsNumL();
	}


void CMTPReferenceMgr::IncTranOpsNumL()
	{
	iObjectStore.IncTranOpsNumL();
	}


/**
Verify if every reference is pointing to a valid object. If the referenced object does not exist,
delete the object from the reference array.
@param aReference	The 64bit internal object identifiers of the referenced objects
@leave One of the system wide error codes, if a processing failure occurs.
*/
/*
void CMTPReferenceMgr::AdjustReferencesL(RArray<TUint32>&aHandles) const
	{
	TInt count = aHandles.Count();
	while(count--)
		{
		if(!iObjectStore.ObjectExistsL(aHandles[count]))
			{
			aHandles.Remove(count);
			}
		}
	}
	*/