metadataengine/server/src/mdsmanipulationengine.cpp
changeset 0 c53acadfccc6
child 2 b73a2e62868f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metadataengine/server/src/mdsmanipulationengine.cpp	Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,1064 @@
+/*
+* Copyright (c) 2007-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:  This is Manipulation engine to manage adding,
+*                deleting and modifying metadata database entries
+*
+*/
+
+// INCLUDE FILES
+#include "mdsmanipulationengine.h"
+
+#include "mdcresult.h"
+#include "mdcitem.h"
+#include "mdsschema.h"
+#include "mdsnotifier.h"
+#include "mdsdbconnectionpool.h"
+#include "mdslogger.h"
+#include "mdssqlobjectmanipulate.h"
+#include "mdssqliteconnection.h"
+#include "mdsnamespacedef.h"
+#include "mdcserializationbuffer.h"
+#include "mdeinternalerror.h"
+#include "mdeerror.h"
+
+__USES_LOGGER
+
+// ======== LOCAL FUNCTIONS ========
+
+static void TransactionCleanupL(void* aConn)
+   {
+   CMdSSqLiteConnection* conn = (CMdSSqLiteConnection*)aConn;
+   conn->TransactionRollbackL();
+   }
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CMdSManipulationEngine* CMdSManipulationEngine::NewL( CMdsSchema& aSchema,
+    CMdSNotifier& aNotifier, CMdSObjectLockList& aLockList )
+    {
+    CMdSManipulationEngine* self = CMdSManipulationEngine::NewLC( aSchema, 
+    		aNotifier, aLockList );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// NewLC
+// ---------------------------------------------------------------------------
+//
+CMdSManipulationEngine* CMdSManipulationEngine::NewLC( CMdsSchema& aSchema,
+    CMdSNotifier& aNotifier, CMdSObjectLockList& aLockList )
+    {
+    CMdSManipulationEngine* self = new (ELeave) CMdSManipulationEngine(
+        aSchema, aNotifier, aLockList );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Default constructor
+// ---------------------------------------------------------------------------
+//
+CMdSManipulationEngine::CMdSManipulationEngine( CMdsSchema& aSchema,
+    CMdSNotifier& aNotifier, CMdSObjectLockList& aLockList )
+    : iManipulate( NULL ), iSchema( aSchema ), iNotifier( aNotifier ), 
+    iGarbageCollector( NULL ), iLockList( aLockList )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::ConstructL()
+    {
+    iManipulate = CMdSSqlObjectManipulate::NewL( iSchema, iLockList );
+    iGarbageCollector = CMdSGarbageCollector::NewL(*this);
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMdSManipulationEngine::~CMdSManipulationEngine()
+    {
+    delete iManipulate;
+    
+    delete iGarbageCollector;
+    }
+
+// ---------------------------------------------------------------------------
+// Manipulate
+// ---------------------------------------------------------------------------
+//
+CMdSSqlObjectManipulate& CMdSManipulationEngine::Manipulate()
+    {
+    return *iManipulate;
+    }
+
+// ---------------------------------------------------------------------------
+// GarbageCollector
+// ---------------------------------------------------------------------------
+//
+CMdSGarbageCollector& CMdSManipulationEngine::GarbageCollector()
+	{
+	return *iGarbageCollector;
+	}
+
+// ---------------------------------------------------------------------------
+// AddL adds objects from serialized buffer
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::AddL( CMdCSerializationBuffer& aBuffer, 
+		CMdCSerializationBuffer& aResultBuffer, 
+		const CMdSServerSession* aServerSession )
+	{
+	const TMdCItems& items = TMdCItems::GetFromBufferL( aBuffer );
+
+	const CMdsNamespaceDef* namespaceDef = iSchema.GetNamespaceByIdL( 
+			items.iNamespaceDefId );
+	if ( !namespaceDef )
+		{
+		User::Leave( KErrMdEUnknownNamespaceDef );
+		}
+	iManipulate->SetNamespace( namespaceDef );
+
+	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+
+	TMdCItemIds resultIds;
+	resultIds.iNamespaceDefId = items.iNamespaceDefId;
+	resultIds.iErrorCode = KErrNone;
+	aResultBuffer.PositionL( sizeof(TMdCItemIds) );
+
+	// add objects
+	const TInt KObjectCount = items.iObjects.iPtr.iCount;
+	if ( KObjectCount > 0 )
+		{
+		resultIds.iObjectIds.iPtr.iOffset = aResultBuffer.Position();
+		resultIds.iObjectIds.iPtr.iCount = items.iObjects.iPtr.iCount;
+
+        RMdsStatement baseObjStmt;
+        CleanupClosePushL(baseObjStmt);
+        RMdsStatement objStmt;
+        CleanupClosePushL(objStmt);
+		
+		if( KObjectCount > 1 )
+		    {
+	        RMdSTransaction transaction( connection );
+	        CleanupClosePushL(transaction);
+	        const TInt beginError( transaction.Error() );
+	        if( beginError != KErrNone )
+	            {
+	            CleanupStack::PopAndDestroy( &transaction );
+	            }
+	    
+		    for ( TInt i = 0; i < KObjectCount; ++i )
+			    {
+			    aBuffer.PositionL( items.iObjects.iPtr.iOffset + i * sizeof(TMdCObject) );
+			    TItemId id = KNoId;
+			    TRAPD( err, id = iManipulate->AddObjectL( connection, aBuffer, 
+			            baseObjStmt, objStmt, aServerSession ) );
+			    if (err == KErrNone)
+				    {
+				    aResultBuffer.InsertL( id );
+				    }
+			    else
+				    {
+				    aResultBuffer.InsertL( KNoId );
+				    if(resultIds.iErrorCode == KErrNone)
+					    {
+					    resultIds.iErrorCode = err;
+					    }
+				    }
+			    }
+		    if( beginError == KErrNone )
+		        {
+	            transaction.CommitL();
+	            CleanupStack::PopAndDestroy( &transaction );
+		        }
+		    }
+		else
+		    {
+            for ( TInt i = 0; i < KObjectCount; ++i )
+                {
+                aBuffer.PositionL( items.iObjects.iPtr.iOffset + i * sizeof(TMdCObject) );
+                TItemId id = KNoId;
+                TRAPD( err, id = iManipulate->AddObjectL( connection, aBuffer, 
+                        baseObjStmt, objStmt, aServerSession ) );
+                if (err == KErrNone)
+                    {
+                    aResultBuffer.InsertL( id );
+                    }
+                else
+                    {
+                    aResultBuffer.InsertL( KNoId );
+                    if(resultIds.iErrorCode == KErrNone)
+                        {
+                        resultIds.iErrorCode = err;
+                        }
+                    }
+                }
+		    }
+        CleanupStack::PopAndDestroy(&objStmt);
+        CleanupStack::PopAndDestroy(&baseObjStmt);
+		}
+	else
+		{
+		resultIds.iObjectIds.iPtr.iOffset = KNoOffset;
+		resultIds.iObjectIds.iPtr.iCount = 0;
+		}
+
+	 // add events
+    const TInt KEventCount = items.iEvents.iPtr.iCount;
+    if ( KEventCount > 0 )
+		{
+		resultIds.iEventIds.iPtr.iOffset = aResultBuffer.Position();
+		resultIds.iEventIds.iPtr.iCount = KEventCount;
+	    
+	    if( KEventCount > 1 )
+	        {
+	        //More than 1 event, transaction will be used.
+	        connection.TransactionBeginL();
+	        CleanupStack::PushL(TCleanupItem(&TransactionCleanupL, &connection));
+	        }
+
+		for ( TInt i = 0; i < KEventCount; ++i )
+			{
+			aBuffer.PositionL( items.iEvents.iPtr.iOffset + 
+					i * sizeof(TMdCEvent) );
+
+			TItemId id = KNoId;
+			TRAPD( err, id = iManipulate->AddEventL( connection, aBuffer ) );
+			if (err == KErrNone)
+				{
+				aResultBuffer.InsertL( id );
+				}
+			else
+				{
+				aResultBuffer.InsertL( KNoId );
+				if(resultIds.iErrorCode == KErrNone)
+					{
+					resultIds.iErrorCode = err;
+					}
+				}
+			}
+
+		if( KEventCount > 1 )
+		    {
+		    connection.TransactionCommitL();
+		    CleanupStack::Pop();  //TransactionCleanup()
+	        }
+		}
+	else
+		{
+		resultIds.iEventIds.iPtr.iOffset = KNoOffset;
+		resultIds.iEventIds.iPtr.iCount = 0;
+		}
+
+	// add relations
+    const TInt KRelationCount = items.iRelations.iPtr.iCount;
+    if ( KRelationCount > 0 )
+		{
+		resultIds.iRelationIds.iPtr.iOffset = aResultBuffer.Position();
+		resultIds.iRelationIds.iPtr.iCount = KRelationCount;
+	    
+	    if( KRelationCount > 1 )
+	        {
+	        //More than 1 relation, transaction will be used.
+	        connection.TransactionBeginL();
+	        CleanupStack::PushL(TCleanupItem(&TransactionCleanupL, &connection));
+	        }
+
+	    for ( TInt i = 0; i < KRelationCount; ++i )
+			{
+			aBuffer.PositionL( items.iRelations.iPtr.iOffset + 
+					i * sizeof(TMdCRelation) );
+
+			TItemId id = KNoId;
+			TRAPD( err, id = iManipulate->AddRelationL( connection, aBuffer ) );
+			if (err == KErrNone)
+				{
+				aResultBuffer.InsertL( id );
+				}
+			else
+				{
+				aResultBuffer.InsertL( KNoId );
+				if(resultIds.iErrorCode == KErrNone)
+					{
+					resultIds.iErrorCode = err;
+					}
+				}
+			}
+
+	    if( KRelationCount > 1 )
+	        {
+	        connection.TransactionCommitL();
+	        CleanupStack::Pop();   //TransactionCleanup()
+	        }
+		}
+	else
+		{
+		resultIds.iRelationIds.iPtr.iOffset = KNoOffset;
+		resultIds.iRelationIds.iPtr.iCount = 0;
+		}
+
+	// set up result header
+	aResultBuffer.PositionL( KNoOffset );
+	resultIds.SerializeL( aResultBuffer );
+
+	iManipulate->SetNamespace( NULL );
+	iNotifier.NotifyAddedL( aBuffer, aResultBuffer );
+	}
+
+// ---------------------------------------------------------------------------
+// RemoveL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::RemoveL( CMdCSerializationBuffer& aBuffer, 
+		CMdCSerializationBuffer& aResultBuffer )
+    {
+    // Read item ids from buffer.
+    const TMdCItemIds& itemIds = TMdCItemIds::GetFromBufferL( aBuffer );
+    
+	const CMdsNamespaceDef* namespaceDef = iSchema.GetNamespaceByIdL( 
+			itemIds.iNamespaceDefId );
+	if ( !namespaceDef )
+		{
+		User::Leave( KErrMdEUnknownNamespaceDef );
+		}
+	iManipulate->SetNamespace( namespaceDef );
+
+    TMdCItemIds resultIds;
+	resultIds.iNamespaceDefId = itemIds.iNamespaceDefId;
+	resultIds.iErrorCode = KErrNone;
+	resultIds.iObjectUris.iPtr.iCount = 0;
+	resultIds.iObjectUris.iPtr.iOffset = KNoOffset;
+
+	aResultBuffer.PositionL( sizeof(TMdCItemIds) );
+
+	RArray<TItemId> idArray;
+	CleanupClosePushL( idArray );
+	RArray<TItemId> removedRelations;
+	CleanupClosePushL( removedRelations );
+	RArray<TItemId> removedEvents;
+	CleanupClosePushL( removedEvents );
+
+    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+
+    // Remove objects by id or URI.
+    if (itemIds.iObjectIds.iPtr.iCount + itemIds.iObjectUris.iPtr.iCount > 0)
+		{
+	    RMdSTransaction transaction( connection );
+	    CleanupClosePushL(transaction);
+	    User::LeaveIfError( transaction.Error() );
+
+		if (itemIds.iObjectUris.iPtr.iCount > 0)
+			{
+			aBuffer.PositionL( itemIds.iObjectUris.iPtr.iOffset );
+			iManipulate->RemoveObjectsByUriL( aBuffer, itemIds.iObjectUris.iPtr.iCount,
+					idArray, removedRelations, removedEvents );
+			}
+		else
+			{
+			aBuffer.PositionL( itemIds.iObjectIds.iPtr.iOffset );
+			iManipulate->RemoveObjectsByIdL( aBuffer, itemIds.iObjectIds.iPtr.iCount,
+					idArray, removedRelations, removedEvents );
+			}
+
+	    transaction.CommitL();
+		CleanupStack::PopAndDestroy( &transaction );
+
+        // write it to the buffer
+        const TInt count = idArray.Count();
+		resultIds.iObjectIds.iPtr.iOffset = aResultBuffer.Position();
+        resultIds.iObjectIds.iPtr.iCount = count;
+        
+        for ( TInt i = 0; i < count; ++i )
+        	{
+        	aResultBuffer.InsertL( idArray[i] );
+        	if (idArray[i] == KNoId && resultIds.iErrorCode==KErrNone)
+        		{
+        		resultIds.iErrorCode = KErrNotFound;
+        		}
+        	}
+        idArray.Reset();
+		}
+    else
+    	{
+    	resultIds.iObjectIds.iPtr.iCount = 0;
+    	resultIds.iObjectIds.iPtr.iOffset = KNoOffset;
+    	}
+
+    // Remove events by id.
+	if (itemIds.iEventIds.iPtr.iCount > 0)
+		{
+		// process events
+		aBuffer.PositionL( itemIds.iEventIds.iPtr.iOffset );
+
+	    RMdSTransaction transaction( connection );
+	    CleanupClosePushL(transaction);
+	    User::LeaveIfError( transaction.Error() );
+
+		iManipulate->RemoveEventsL( aBuffer, itemIds.iEventIds.iPtr.iCount, idArray );
+
+	    transaction.CommitL();
+		CleanupStack::PopAndDestroy( &transaction );
+
+        const TInt count = idArray.Count();
+        resultIds.iEventIds.iPtr.iOffset = aResultBuffer.Position();
+        resultIds.iEventIds.iPtr.iCount = count;
+
+        for ( TInt i = 0; i < count; ++i )
+        	{
+        	aResultBuffer.InsertL( idArray[i] );
+        	if (idArray[i] == KNoId && resultIds.iErrorCode==KErrNone)
+        		{
+        		resultIds.iErrorCode = KErrNotFound;
+        		}
+        	}
+		idArray.Reset();
+		}
+	else
+		{
+        resultIds.iEventIds.iPtr.iOffset = KNoOffset;
+        resultIds.iEventIds.iPtr.iCount = 0;
+		}
+
+	// Remove relations by id.
+	if (itemIds.iRelationIds.iPtr.iCount > 0)
+		{
+		// process relations
+		aBuffer.PositionL( itemIds.iRelationIds.iPtr.iOffset );
+
+	    RMdSTransaction transaction( connection );
+	    CleanupClosePushL(transaction);
+	    User::LeaveIfError( transaction.Error() );
+
+		iManipulate->RemoveRelationsL( aBuffer, itemIds.iRelationIds.iPtr.iCount, idArray );
+
+	    transaction.CommitL();
+		CleanupStack::PopAndDestroy( &transaction );
+
+        const TInt count = idArray.Count();
+        resultIds.iRelationIds.iPtr.iOffset = aResultBuffer.Position();
+        resultIds.iRelationIds.iPtr.iCount = count;
+
+        for ( TInt i = 0; i < count; ++i )
+        	{
+        	aResultBuffer.InsertL( idArray[i] );
+        	if (idArray[i] == KNoId && resultIds.iErrorCode==KErrNone)
+        		{
+        		resultIds.iErrorCode = KErrNotFound;
+        		}
+        	}
+		}
+	else
+		{
+        resultIds.iRelationIds.iPtr.iOffset = KNoOffset;
+        resultIds.iRelationIds.iPtr.iCount = 0;
+		}
+
+	aResultBuffer.PositionL( KNoOffset );
+	resultIds.SerializeL( aResultBuffer );
+
+	// notify about items removed
+	const TBool notify = iNotifier.CheckForNotifier(EObjectNotifyRemove|EEventNotifyRemove|ERelationNotifyRemove);
+	if (notify)
+		{
+		iNotifier.NotifyRemovedL( aResultBuffer, EFalse );
+		}
+
+	// notify about additional items removed
+	const TInt KRemovedItemsCount = removedRelations.Count() + removedEvents.Count();
+    if ( notify && KRemovedItemsCount > 0 )
+    	{
+    	const TInt32 bufferSize = sizeof(TMdCItemIds)
+							+ KRemovedItemsCount * CMdCSerializationBuffer::KRequiredSizeForTItemId;
+
+		CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( bufferSize );
+
+		buffer->PositionL( sizeof(TMdCItemIds) );
+		
+		TMdCItemIds additResultIds;
+		additResultIds.iNamespaceDefId = itemIds.iNamespaceDefId;
+		additResultIds.iErrorCode = KErrNone;
+		additResultIds.iObjectIds.iPtr.iOffset = KNoOffset;
+		additResultIds.iObjectIds.iPtr.iCount = 0;
+		additResultIds.iObjectUris.iPtr.iOffset = KNoOffset;
+		additResultIds.iObjectUris.iPtr.iCount = 0;
+
+		// Insert list of removed events to the serialization buffer.
+		const TInt KRemovedEventsCount = removedEvents.Count();
+		additResultIds.iEventIds.iPtr.iCount = KRemovedEventsCount;
+		if ( KRemovedEventsCount > 0 )
+			{
+			additResultIds.iEventIds.iPtr.iOffset = buffer->Position();
+			for ( TInt i = 0; i < KRemovedEventsCount; ++i )
+				{
+				buffer->InsertL( removedEvents[i] );
+				}
+			}
+		else
+			{
+			additResultIds.iEventIds.iPtr.iOffset = KNoOffset;
+			}
+
+		// Insert list of removed relations to the serialization buffer.
+		const TInt KRemovedRelationsCount = removedRelations.Count();
+		additResultIds.iRelationIds.iPtr.iCount = KRemovedRelationsCount;
+		if ( KRemovedRelationsCount > 0 )
+			{
+			additResultIds.iRelationIds.iPtr.iOffset = buffer->Position();
+			for ( TInt i = 0; i < KRemovedRelationsCount; ++i )
+				{
+				buffer->InsertL( removedRelations[i] );
+				}
+			}
+		else
+			{
+			additResultIds.iRelationIds.iPtr.iOffset = KNoOffset;
+			}
+
+		buffer->PositionL( KNoOffset );
+		additResultIds.SerializeL( *buffer );
+		iNotifier.NotifyRemovedL( *buffer, EFalse );
+		CleanupStack::PopAndDestroy( buffer );
+    	}
+
+    // notify about removed relation items
+	const TInt relationsCount = removedRelations.Count() + idArray.Count();
+	
+    if ( relationsCount > 0 && iNotifier.CheckForNotifier(ERelationItemNotifyRemove) )
+    	{
+		CMdCSerializationBuffer* itemsBuffer = CMdCSerializationBuffer::NewLC( 
+				sizeof( TMdCItems ) + 
+				sizeof( TMdCRelation ) * relationsCount );
+
+		iManipulate->GetRemovedRelationItemsL( *itemsBuffer, 
+				removedRelations, idArray );
+
+		iNotifier.NotifyRemovedRelationItemsL( *itemsBuffer );
+
+		CleanupStack::PopAndDestroy( itemsBuffer );
+    	}
+    
+	// start garbage collector
+	if( iGarbageCollector )
+		{
+		iGarbageCollector->Start( KGarbageCollectionDelay );
+		}
+
+	// removedEvents, removedRelations, idArray
+    CleanupStack::PopAndDestroy( 3, &idArray );
+    }
+
+void CMdSManipulationEngine::UpdateL( CMdCSerializationBuffer& aBuffer, 
+		CMdCSerializationBuffer& aResultBuffer )
+	{
+	const TMdCItems& items = TMdCItems::GetFromBufferL( aBuffer );
+
+	const CMdsNamespaceDef* namespaceDef = iSchema.GetNamespaceByIdL( 
+			items.iNamespaceDefId );
+	if ( !namespaceDef )
+		{
+		User::Leave( KErrMdEUnknownNamespaceDef );
+		}
+	iManipulate->SetNamespace( namespaceDef );
+    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+
+	TMdCItemIds resultIds;
+	resultIds.iNamespaceDefId = items.iNamespaceDefId;
+	resultIds.iErrorCode = KErrNone;
+	resultIds.iObjectUris.iPtr.iOffset = KNoOffset;
+	resultIds.iObjectUris.iPtr.iCount = 0;
+	resultIds.iEventIds.iPtr.iOffset = KNoOffset;
+	resultIds.iEventIds.iPtr.iCount = 0;
+
+	aResultBuffer.PositionL( sizeof(TMdCItemIds) );
+
+	// update objects
+	if ( items.iObjects.iPtr.iCount > 0 )
+		{
+		resultIds.iObjectIds.iPtr.iOffset = aResultBuffer.Position();
+		resultIds.iObjectIds.iPtr.iCount = items.iObjects.iPtr.iCount;
+
+		for ( TInt i = 0; i < items.iObjects.iPtr.iCount; ++i )
+			{
+			aBuffer.PositionL( items.iObjects.iPtr.iOffset + i * sizeof(TMdCObject) );
+
+			TItemId id = KNoId;
+			TRAPD( err, id = iManipulate->UpdateObjectL( connection, aBuffer ) );
+			if (err == KErrNone)
+				{
+				aResultBuffer.InsertL( id );
+				}
+			else
+				{
+				aResultBuffer.InsertL( KNoId );
+				if ( resultIds.iErrorCode == KErrNone )
+					{
+					resultIds.iErrorCode = err;
+					}
+				}
+			}
+		}
+	else
+		{
+		resultIds.iObjectIds.iPtr.iOffset = KNoOffset;
+		resultIds.iObjectIds.iPtr.iCount = 0;
+		}
+
+	// update relations
+	if ( items.iRelations.iPtr.iCount > 0 )
+		{
+		resultIds.iRelationIds.iPtr.iOffset = aResultBuffer.Position();
+		resultIds.iRelationIds.iPtr.iCount = items.iRelations.iPtr.iCount;
+
+		for ( TInt i = 0; i < items.iRelations.iPtr.iCount; ++i )
+			{
+			aBuffer.PositionL( items.iRelations.iPtr.iOffset + i * sizeof(TMdCRelation) );
+
+			TItemId id = KNoId;
+			TRAPD( err, id = iManipulate->UpdateRelationsL( connection, aBuffer ) );
+			if (err == KErrNone)
+				{
+				aResultBuffer.InsertL( id );
+				}
+			else
+				{
+				aResultBuffer.InsertL( KNoId );
+				if ( resultIds.iErrorCode == KErrNone )
+					{
+					resultIds.iErrorCode = err;
+					}
+				}
+			}
+		}
+	else
+		{
+		resultIds.iRelationIds.iPtr.iOffset = KNoOffset;
+		resultIds.iRelationIds.iPtr.iCount = 0;
+		}
+
+	if ( items.iEvents.iPtr.iCount > 0 )
+		{
+		// events cannot be updated
+		// so just ignore it, but if possible return error code
+		if ( resultIds.iErrorCode == KErrNone )
+			{
+			resultIds.iErrorCode = KErrArgument;
+			}
+		}
+
+	iManipulate->SetNamespace( NULL );
+
+	// set up result header
+	aResultBuffer.PositionL( KNoOffset );
+	resultIds.SerializeL( aResultBuffer );
+
+	iNotifier.NotifyModifiedL( aBuffer, aResultBuffer );
+    }
+
+CMdCSerializationBuffer* CMdSManipulationEngine::CheckObjectL( 
+		TInt aResultBufferSize, const TDesC& aUri, TDefId aNamespaceDefId )
+	{
+    return iManipulate->CheckObjectL( 
+    		aResultBufferSize, aUri, aNamespaceDefId );
+	}
+
+CMdCSerializationBuffer* CMdSManipulationEngine::CheckObjectL( 
+		TInt aResultBufferSize, TItemId aId, TDefId aNamespaceDefId )
+	{
+    return iManipulate->CheckObjectL( 
+    		aResultBufferSize, aId, aNamespaceDefId );
+	}
+
+CMdCSerializationBuffer* CMdSManipulationEngine::CheckObjectL( 
+		TInt aResultBufferSize, CMdCSerializationBuffer& aIds, 
+		TDefId aNamespaceDefId )
+	{
+	return iManipulate->CheckObjectL( 
+			aResultBufferSize, aIds, aNamespaceDefId );
+	}
+
+// ---------------------------------------------------------------------------
+// AddMemoryCardL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::AddMemoryCardL(TUint32 aMediaId)
+	{
+	iManipulate->AddMemoryCardL( aMediaId );
+	}
+
+// ---------------------------------------------------------------------------
+// GetMemoryCardL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::GetMemoryCardL(TUint32& aMediaId)
+	{
+	iManipulate->GetMemoryCardL( aMediaId );
+	}
+
+// ---------------------------------------------------------------------------
+// CheckMemoryCardL
+// ---------------------------------------------------------------------------
+//
+TBool CMdSManipulationEngine::CheckMemoryCardL(TUint32 aMediaId)
+	{
+	return iManipulate->CheckMemoryCardL( aMediaId );
+	}
+
+// ---------------------------------------------------------------------------
+// SetMediaL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::SetMediaL(TUint32 aMediaId, TChar aDrive, 
+		TBool aPresentState)
+	{
+	return iManipulate->SetMediaL( aMediaId, aDrive, aPresentState );
+	}
+	
+// ---------------------------------------------------------------------------
+// GetMediaL
+// ---------------------------------------------------------------------------
+//
+TBool CMdSManipulationEngine::GetMediaL(TUint32 aMediaId, TChar& aDrive, 
+		TBool& aPresentState)
+	{
+	return iManipulate->GetMediaL( aMediaId, aDrive, aPresentState );
+	}
+
+// ---------------------------------------------------------------------------
+// GetPresentMediasL
+// ---------------------------------------------------------------------------
+//
+TInt32 CMdSManipulationEngine::GetPresentMediasL(TDes8& aMediaInfoBuffer)
+	{
+	return iManipulate->GetPresentMediasL( aMediaInfoBuffer );
+	}
+
+// ---------------------------------------------------------------------------
+// SetFilesToPresentL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::SetFilesToPresentL(TUint32 aMediaId, TUint32 aFileCount, 
+		CMdCSerializationBuffer& aUris, CMdCSerializationBuffer& aFileInfos,
+		CMdCSerializationBuffer& aResults)
+	{
+
+    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+    RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+
+    RArray<TItemId> itemIds;
+	CleanupClosePushL( itemIds );
+    itemIds.ReserveL( aFileCount );
+
+    RArray<TItemId> notifyItemIds;
+	CleanupClosePushL( notifyItemIds );
+	notifyItemIds.ReserveL( aFileCount );
+
+    for( TUint32 i = 0; i < aFileCount; i++ )
+    	{
+    	TPtrC16 uri = aUris.ReceivePtr16L();
+    	TPtr16 uriLC( CONST_CAST( TUint16*, uri.Ptr() ), uri.Length(), uri.Length() );
+    	uriLC.LowerCase();
+
+    	TMdSFileInfo fileInfo;
+    	aFileInfos.ReceiveL(fileInfo.iModifiedTime);
+    	aFileInfos.ReceiveL(fileInfo.iSize);
+
+#ifdef _DEBUG    	
+    	const TInt64 time = fileInfo.iModifiedTime;
+        RDebug::Print( _L("CMdSManipulationEngine::SetFilesToPresentL: (%d) iSize %u, iModified %Ld, uri %S"),
+        		i,
+        		fileInfo.iSize,
+        		time,
+        		&uri);
+#endif
+
+    	TFilePresentStates placeHolder;
+    	TBool notPresentState( EFalse );
+    	const TItemId objectId = iManipulate->SearchNotPresentFileL( /*reservation(), */
+    			aMediaId, uri, fileInfo, placeHolder, notPresentState );
+    	if ( placeHolder != EMdsNotFound )
+    		{
+    		itemIds.Append( objectId );
+
+    		if( notPresentState )
+    			{
+    			notifyItemIds.Append( objectId );
+    			}
+    		}
+
+    	aResults.InsertL( (TUint8)placeHolder );
+    	}
+
+	iManipulate->SetFilesToPresentL( itemIds );
+
+	// only notify about objects in not present state and
+	// modify and notify relations related to those
+	if( notifyItemIds.Count() > 0 )
+		{
+		iNotifier.NotifyObjectPresent( ETrue, notifyItemIds );
+
+		RArray<TItemId> relationIds;
+		CleanupClosePushL( relationIds );
+
+	    const TInt itemIdCount = notifyItemIds.Count();
+		for( TUint32 i = 0; i < itemIdCount; i++ )
+			{
+			iManipulate->SetRelationsToPresentL( notifyItemIds[i], relationIds );
+			}
+
+		iNotifier.NotifyRelationPresent( ETrue, relationIds );
+
+		CleanupStack::PopAndDestroy( &relationIds );
+		}
+
+	transaction.CommitL();
+
+	CleanupStack::PopAndDestroy( &notifyItemIds );
+	CleanupStack::PopAndDestroy( &itemIds );
+
+	CleanupStack::PopAndDestroy( &transaction );
+	}
+
+// ---------------------------------------------------------------------------
+// SetFilesToNotPresentL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::SetFilesToNotPresentL(TUint32 aMediaId, TBool aStartUp)
+	{
+    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+    RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+	
+	RArray<TItemId> objectIds;
+	CleanupClosePushL( objectIds );
+
+	iManipulate->SetFilesToNotPresentL( aMediaId, aStartUp, objectIds );
+	
+	// if start up no need for object notifications, 
+	// setting relations to not present and relation notifications
+	if( !aStartUp )
+		{
+		iNotifier.NotifyObjectPresent( EFalse, objectIds );
+		
+		RArray<TItemId> relationIds;
+		CleanupClosePushL( relationIds );
+	
+        iManipulate->SetRelationsToNotPresentL( aMediaId, relationIds );
+		iNotifier.NotifyRelationPresent( EFalse, relationIds );
+		
+		CleanupStack::PopAndDestroy( &relationIds );
+		}
+    
+    transaction.CommitL();
+
+    CleanupStack::PopAndDestroy( &objectIds );
+    CleanupStack::PopAndDestroy( &transaction );
+	}
+
+// ---------------------------------------------------------------------------
+// RemoveFilesNotPresentL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::RemoveFilesNotPresentL(TUint32 aMediaId, TBool aStartUp)
+	{
+    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+    RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+	
+	if( aStartUp )
+		{
+		RArray<TItemId> objectIds;
+		CleanupClosePushL( objectIds );
+
+		iManipulate->RemoveFilesNotPresentL( aMediaId, &objectIds );
+		
+		if( objectIds.Count() > 0 )
+			{
+			iNotifier.NotifyRemovedL( objectIds );
+			}
+		
+		CleanupStack::PopAndDestroy( &objectIds );
+		}
+	else
+		{
+		iManipulate->RemoveFilesNotPresentL( aMediaId, NULL );
+		}
+
+    transaction.CommitL();
+    CleanupStack::PopAndDestroy( &transaction );
+
+	// start garbage collector
+	if( iGarbageCollector )
+		{
+		iGarbageCollector->Start( KGarbageCollectionDelay );
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// StartGarbageCollection
+// ---------------------------------------------------------------------------
+//
+TBool CMdSManipulationEngine::StartGarbageCollectionL()
+	{
+#ifdef _DEBUG
+	RDebug::Print( _L("CMdSManipulationEngine::StartGarbageCollection()") );
+#endif
+
+    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+    RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+	
+    TBool again = EFalse;
+#ifdef _DEBUG
+    TRAPD( err, again = iManipulate->GarbageCollectionL() );
+#else
+    TRAP_IGNORE( again = iManipulate->GarbageCollectionL() );
+#endif
+
+    transaction.CommitL();
+    CleanupStack::PopAndDestroy( &transaction ); 
+    
+	#ifdef _DEBUG
+	if( err != KErrNone )
+		{
+		_LIT( KErrLog, "CMdSManipulationEngine::StartGarbageCollection error: %d" );
+		RDebug::Print( KErrLog, err );		
+		}
+	#endif
+	
+	return again;
+	}
+
+// ---------------------------------------------------------------------------
+// GetSchemaVersionL
+// ---------------------------------------------------------------------------
+//
+void CMdSManipulationEngine::GetSchemaVersionL(
+		TInt& aMajorVersion, TInt& aMinorVersion)
+	{
+	iManipulate->GetSchemaVersionL( aMajorVersion, aMinorVersion );
+	}
+
+void CMdSManipulationEngine::SetObjectToPresentByGuidL( 
+		const TInt64& aGuidHigh, const TInt64& aGuidLow )
+	{
+	iManipulate->SetObjectToPresentByGuidL( aGuidHigh, aGuidLow );
+	}
+
+void CMdSManipulationEngine::ChangePathL(const TDesC& aOldPath, const TDesC& aNewPath)
+	{
+	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+    RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+	
+	RArray<TItemId> objectIds;
+	CleanupClosePushL( objectIds );
+
+	iManipulate->ChangePathL( aOldPath, aNewPath, objectIds );
+
+	iNotifier.NotifyModifiedL( objectIds );
+	
+	CleanupStack::PopAndDestroy( &objectIds );
+	
+	transaction.CommitL();
+    CleanupStack::PopAndDestroy( &transaction );
+	}
+
+void CMdSManipulationEngine::ChangeMediaIdL()
+	{
+	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+    RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+	
+	iManipulate->ChangeMediaIdL();
+	
+	transaction.CommitL();
+
+	CleanupStack::PopAndDestroy( &transaction );
+	}
+
+void CMdSManipulationEngine::AddRelationDefL( TDefId aNamespaceId, const TDesC& aRelationDefName )
+	{
+	CMdsNamespaceDef* namespaceDef = CONST_CAST( CMdsNamespaceDef*, iSchema.GetNamespaceByIdL( aNamespaceId ) );
+	if ( !namespaceDef )
+		{
+		User::Leave( KErrMdEUnknownNamespaceDef );
+		}
+	if ( namespaceDef->GetReadOnly() )
+		{
+		User::Leave( KErrLocked );
+		}
+
+	namespaceDef->AddRelationDefL( aRelationDefName );
+	iSchema.StoreToDBL();
+	}
+
+void CMdSManipulationEngine::AddEventDefL( TDefId aNamespaceId, const TDesC& aEventDefName )
+	{
+	CMdsNamespaceDef* namespaceDef = CONST_CAST( CMdsNamespaceDef*, iSchema.GetNamespaceByIdL( aNamespaceId ) );
+	if ( !namespaceDef )
+		{
+		User::Leave( KErrMdEUnknownNamespaceDef );
+		}
+	if ( namespaceDef->GetReadOnly() )
+		{
+		User::Leave( KErrLocked );
+		}
+
+	namespaceDef->AddEventDefL( aEventDefName, 1 );
+	iSchema.StoreToDBL();
+	}
+
+void CMdSManipulationEngine::SetPendingL(const RArray<TItemId>& aObjectIds)
+	{
+	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+	RMdSTransaction transaction( connection );
+	CleanupClosePushL( transaction );
+	User::LeaveIfError( transaction.Error() );
+
+	iManipulate->SetPendingL( aObjectIds, EFalse );
+
+	transaction.CommitL();
+    CleanupStack::PopAndDestroy( &transaction );
+	}
+
+void CMdSManipulationEngine::ResetPendingL(const RArray<TItemId>& aObjectIds)
+	{
+	iManipulate->SetPendingL( aObjectIds, ETrue );
+	}
+
+TInt CMdSManipulationEngine::GetPendingCountL( TDefId aObjectDefId )
+	{
+	return iManipulate->GetPendingCountL( aObjectDefId );
+	}
+
+TInt CMdSManipulationEngine::GetPendingL( TDefId aObjectDefId, 
+		TInt aBufferSize, RArray<TItemId>& aObjectIds )
+	{
+	return iManipulate->GetPendingL( aObjectDefId, aBufferSize, aObjectIds );
+	}