syncmlfw/dm/treemodule/src/nsmldmcommandbuffer.cpp
changeset 0 b497e44ab2fc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/syncmlfw/dm/treemodule/src/nsmldmcommandbuffer.cpp	Thu Dec 17 09:07:52 2009 +0200
@@ -0,0 +1,714 @@
+/*
+* Copyright (c) 2005 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:  DM tree etc.
+*
+*/
+
+#include "nsmldmcommandbuffer.h"
+#include "nsmldmtreeconstants.h"
+#include "nsmldmddf.h"
+#include "nsmldmuri.h"
+
+
+// ===========================================================================
+// CNSmlDmCommandBuffer
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::~CNSmlDmCommandBuffer()
+// ---------------------------------------------------------------------------
+CNSmlDmCommandBuffer::~CNSmlDmCommandBuffer()
+	{
+	if(iCommandBuffer !=0 )
+	    {
+	    CNSmlDmCommands* tmp=iCommandBuffer;
+    	    while(tmp!=0)
+    		{
+        		tmp=iCommandBuffer->iNext;
+        		delete iCommandBuffer;
+        		iCommandBuffer = tmp;
+    		}
+	    }
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::CNSmlDmCommandBuffer()
+// ---------------------------------------------------------------------------
+CNSmlDmCommandBuffer::CNSmlDmCommandBuffer(CNSmlDmModule& aDmModule)
+	:iDmModule(aDmModule)
+	{
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer* CNSmlDmCommandBuffer::NewL()
+// ---------------------------------------------------------------------------
+CNSmlDmCommandBuffer* CNSmlDmCommandBuffer::NewL(CNSmlDmModule& aDmModule)
+	{
+	CNSmlDmCommandBuffer* self = new (ELeave) CNSmlDmCommandBuffer(aDmModule);
+	return self;
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::AddObjectL()
+// Adds an Add command to the command buffer. The command is executed
+// in Commit
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::AddObjectL(const TDesC8& aURI,
+	const TDesC8& aObject,
+	const TDesC8& aType,
+	TInt aStatusRef )
+	{
+	CNSmlDmCommands* cmd = new (ELeave) CNSmlDmCommands;
+	CleanupStack::PushL(cmd);
+	
+	cmd->iURI = aURI.AllocL();
+	cmd->iObject = aObject.AllocL();
+	cmd->iType = aType.AllocL();
+	cmd->iStatusRef = aStatusRef;
+	cmd->iCmdType = EAclAdd;
+
+	if(iCommandBuffer==0)
+		{
+		iCommandBuffer = cmd;
+		}
+	else
+		{
+		CNSmlDmCommands* tmp=iCommandBuffer;
+		while(tmp->iNext!=0)
+			{
+			tmp=tmp->iNext;
+			}
+		tmp->iNext = cmd;
+		}
+	CleanupStack::Pop(); //cmd
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::UpdateObjectL()
+// Adds an Update command to the command buffer. The command is executed
+// in Commit
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::UpdateObjectL( const TDesC8& aURI,
+	const TDesC8& aObject,
+	const TDesC8& aType,
+	TInt aStatusRef)
+	{
+	CNSmlDmCommands* cmd = new (ELeave) CNSmlDmCommands;
+	CleanupStack::PushL(cmd);
+	
+	cmd->iURI = aURI.AllocL();
+	cmd->iObject = aObject.AllocL();
+	cmd->iType = aType.AllocL();
+	cmd->iStatusRef = aStatusRef;
+	cmd->iCmdType = EAclReplace;
+
+	if(iCommandBuffer==0)
+		{
+		iCommandBuffer = cmd;
+		}
+	else
+		{
+		CNSmlDmCommands* tmp=iCommandBuffer;
+		while(tmp->iNext!=0)
+			{
+			tmp=tmp->iNext;
+			}
+		tmp->iNext = cmd;
+		}
+	CleanupStack::Pop();
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::FetchObjectL()
+// Adds an Fetch command to the command buffer. The command is executed in Commit
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::FetchObjectL(const TDesC8& aURI,
+	const TDesC8& aType,
+	TInt aResultsRef,
+	TInt aStatusRef )
+	{
+	CNSmlDmCommands* cmd = new (ELeave) CNSmlDmCommands;
+	CleanupStack::PushL(cmd);
+	
+	cmd->iURI = aURI.AllocL();
+	cmd->iType = aType.AllocL();
+	cmd->iStatusRef = aStatusRef;
+	cmd->iCmdType = EAclGet;
+	cmd->iResultsRef = aResultsRef;
+
+	if(iCommandBuffer==0)
+		{
+		iCommandBuffer = cmd;
+		}
+	else
+		{
+		CNSmlDmCommands* tmp=iCommandBuffer;
+		while(tmp->iNext!=0)
+			{
+			tmp=tmp->iNext;
+			}
+		tmp->iNext = cmd;
+		}
+	CleanupStack::Pop(); //cmd
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::DeleteObjectL()
+// Adds an Delete command to the command buffer. The command is executed
+// in Commit
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::DeleteObjectL( const TDesC8& aURI, TInt aStatusRef)
+	{
+	CNSmlDmCommands* cmd = new (ELeave) CNSmlDmCommands;
+	CleanupStack::PushL(cmd);
+	
+	cmd->iURI = aURI.AllocL();
+	cmd->iStatusRef = aStatusRef;
+	cmd->iCmdType = EAclDelete;
+
+	if(iCommandBuffer==0)
+		{
+		iCommandBuffer = cmd;
+		}
+	else
+		{
+		CNSmlDmCommands* tmp=iCommandBuffer;
+		while(tmp->iNext!=0)
+			{
+			tmp=tmp->iNext;
+			}
+		tmp->iNext = cmd;
+		}
+	CleanupStack::Pop(); //cmd
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::ExecuteObjectL()
+// Adds an Execute command to the command buffer. The command is executed
+// in Commit
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::ExecuteObjectL( const TDesC8& aURI,
+	const TDesC8& aObject,
+	const TDesC8& aType,
+	TInt aStatusRef)
+	{
+	CNSmlDmCommands* cmd = new (ELeave) CNSmlDmCommands;
+	CleanupStack::PushL(cmd);
+	
+	cmd->iURI = aURI.AllocL();
+	cmd->iObject = aObject.AllocL();
+	cmd->iType = aType.AllocL();
+	cmd->iStatusRef = aStatusRef;
+	cmd->iCmdType = EAclExecute;
+
+	if(iCommandBuffer==0)
+		{
+		iCommandBuffer = cmd;
+		}
+	else
+		{
+		CNSmlDmCommands* tmp=iCommandBuffer;
+		while(tmp->iNext!=0)
+			{
+			tmp=tmp->iNext;
+			}
+		tmp->iNext = cmd;
+		}
+	CleanupStack::Pop(); //cmd
+	}
+	
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::CopyObjectL()
+// Adds an Copy command to the command buffer. The command is executed
+// in Commit
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::CopyObjectL( const TDesC8& aTargetURI,
+	const TDesC8& aSourceURI,
+	const TDesC8& aType,
+	TInt aStatusRef)
+	{
+	CNSmlDmCommands* cmd = new (ELeave) CNSmlDmCommands;
+	CleanupStack::PushL(cmd);
+	
+	cmd->iURI = aSourceURI.AllocL();
+	cmd->iTargetURI = aTargetURI.AllocL();
+	cmd->iType = aType.AllocL();
+	cmd->iStatusRef = aStatusRef;
+	cmd->iCmdType = EAclCopy;
+
+	if(iCommandBuffer==0)
+		{
+		iCommandBuffer = cmd;
+		}
+	else
+		{
+		CNSmlDmCommands* tmp=iCommandBuffer;
+		while(tmp->iNext!=0)
+			{
+			tmp=tmp->iNext;
+			}
+		tmp->iNext = cmd;
+		}
+	CleanupStack::Pop(); //cmd
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::IsGetWithAtomic()
+// Checks whether nested Get command is there inside atomic command
+// ---------------------------------------------------------------------------
+TBool CNSmlDmCommandBuffer::IsGetWithAtomic()
+{ TBool isget(EFalse);
+	TInt  isnested = -1;
+ CNSmlDmCommands* cmd=iCommandBuffer;
+ 
+ while(cmd !=0)
+ {
+ 	if(cmd->iCmdType == EAclGet)
+    {  
+    	
+    	isget =ETrue;
+    }
+  isnested++;
+  
+  cmd=cmd->iNext;
+ }
+if(isnested > 0 && isget)
+    {
+    	  return ETrue;
+    } 
+    
+  
+ return EFalse;   
+   
+ }
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::CommitL()
+// Executes the commands in commandbuffer. If some of commands fails,
+// the rest of commands are deleted without execution
+// (NotExecuted status is returned)
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::CommitL(  CNSmlDmDDF& aDDF )
+	{
+	aDDF.StartAtomicL();
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	while(cmd!=0)
+		{
+		if(!cmd->iGotStatus)
+			{
+			//check the access from the ddf (not acl)
+			CNSmlDmDDF::TAccess access = aDDF.CheckURIL(
+				NSmlDmURI::RemoveProp(cmd->iURI->Des()),cmd->iCmdType);
+	
+			if(access == CNSmlDmDDF::EOk ) //access ok
+				{
+				TInt offset = cmd->iURI->Find(KNSmlDmProperty);
+				if(offset==KErrNotFound) //not property asked
+					{
+					switch(cmd->iCmdType)
+						{
+						case EAclAdd:
+						aDDF.AddObjectL(*cmd->iURI,*cmd->iObject,
+							*cmd->iType,cmd->iStatusRef);
+						break;
+			
+						case EAclReplace:
+						aDDF.UpdateObjectL(*cmd->iURI,*cmd->iObject,
+							*cmd->iType,cmd->iStatusRef);
+						break;
+			
+						case EAclGet:
+						if(IsGetWithAtomic())
+						{
+							cmd->iStatusCode = KNSmlDmStatusCommandFailed;
+				        cmd->iGotStatus = ETrue;
+						}
+						else
+						aDDF.FetchObjectL(*cmd->iURI,*cmd->iType,
+							cmd->iResultsRef,cmd->iStatusRef);
+						break;
+			
+						case EAclDelete:
+						aDDF.DeleteObjectL(*cmd->iURI,cmd->iStatusRef);
+						break;
+
+						case EAclExecute:
+						// FOTA
+						aDDF.ExecuteObjectL(*cmd->iURI,*cmd->iObject,
+							*cmd->iType,cmd->iStatusRef, KNullDesC8);
+						// FOTA end							
+						break;
+
+						case EAclCopy:
+						aDDF.CopyObjectL(*cmd->iTargetURI,*cmd->iURI,
+							*cmd->iType,cmd->iStatusRef);
+						break;
+						default:
+						User::Panic ( KNSmlTxtPanicDmModule, KErrArgument );
+						break;
+						}
+					}
+				else //property
+					{
+					switch(cmd->iCmdType)
+						{
+						case EAclReplace:
+						iDmModule.UpdatePropertyL(*cmd->iURI,*cmd->iObject,
+							*cmd->iType,offset+KNSmlDmProperty().Length(),
+							cmd->iStatusRef);
+						break;
+			
+						case EAclGet:
+						iDmModule.GetPropertyL(*cmd->iURI,*cmd->iType,
+							KNSmlDmProperty().Length()+offset,
+							cmd->iResultsRef,cmd->iStatusRef);
+						break;
+
+						default:
+						cmd->iStatusCode = KNSmlDmStatusCommandNotAllowed;
+						cmd->iGotStatus = ETrue;
+						break;
+
+						}
+
+					} //end else
+				} //end if(CheckURIL())
+			else if(access == CNSmlDmDDF::ENotAccess )
+				{
+				cmd->iStatusCode = KNSmlDmStatusCommandNotAllowed;
+				cmd->iGotStatus = ETrue;
+				}
+			else
+				{
+				SetStatus(cmd->iStatusRef,KNSmlDmStatusNotFound);
+				}
+			}
+		cmd=cmd->iNext;
+		} //end while
+	aDDF.EndMessageL();
+	if(AtomicFailed())
+		{
+		aDDF.RollbackAtomicL();
+		RollBackL(aDDF);
+		}
+	else
+		{
+		aDDF.CommitAtomicL();		
+		}
+	ChangeAtomicStatuses();
+	SendStatusAndResultCodesL();
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::RollBackL()
+// Returns status NotExecuted to the commands in commandbuffer
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::RollBackL(CNSmlDmDDF& aDDF)
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	TBool loopAgain = EFalse;
+	while(cmd!=0)
+		{
+		if(cmd->iGotStatus &&
+			cmd->iStatusCode==KNSmlDmStatusOK &&
+			cmd->iURI->Find(KNSmlDmProperty)==KErrNotFound)
+			{
+			if(cmd->iCmdType==EAclAdd)
+				{
+				loopAgain=ETrue;
+				delete cmd->iCallback;
+				cmd->iCallback=0;
+				cmd->iCallback = CNSmlDmLinkCallback::NewL();
+				iDmModule.DeleteInTransactionL(*cmd->iURI,cmd->iCallback);
+				}
+			if(cmd->iCmdType!=EAclGet)
+				{
+				cmd->iStatusCode = KNSmlDmStatusAtomicRollBackFailed;
+				}
+			}
+			else if(cmd->iStatusCode != KNSmlDmStatusOK)
+			{	
+				cmd->iStatusCode = KNSmlDmStatusCommandFailed;
+			}
+		cmd=cmd->iNext;
+		}
+
+	if(loopAgain)
+		{
+		cmd=iCommandBuffer;
+		while(cmd!=0)
+			{
+			if(cmd->iCmdType==EAclAdd&&cmd->iCallback)
+				{
+				TInt status = cmd->iCallback->GetStatusL();
+				if(status==KNSmlDmStatusOK || ParentNodeDeletedL(*cmd->iURI) ||
+					(status==KNSmlDmStatusNotFound&&
+					aDDF.CheckURIL(*cmd->iURI,EAclAdd)==CNSmlDmDDF::EOk) )
+					{
+					cmd->iStatusCode = KNSmlDmStatusAtomicRollBackOK;
+					}
+				}
+			else if(cmd->iCmdType==EAclReplace)
+				{
+				if(ParentNodeDeletedL(*cmd->iURI))
+					{
+					cmd->iStatusCode = KNSmlDmStatusAtomicRollBackOK;
+					}
+				}
+			cmd=cmd->iNext;
+			}
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::ChangeAtomicStatuses()
+// Changes all statuses so that they matches to atomic statuses
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::ChangeAtomicStatuses()
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	
+	if(iAtomicFailed)
+		{
+		while(cmd!=0)
+			{
+			if(cmd->iCmdType==EAclReplace &&
+				cmd->iURI->Find(KNSmlDmProperty) &&
+				cmd->iStatusCode == KNSmlDmStatusOK)
+				{
+				cmd->iStatusCode = KNSmlDmStatusAtomicRollBackOK;
+				}
+			if( cmd->iStatusCode<KNSmlDmStatusLargestOK)
+				{
+				cmd->iStatusCode = KNSmlDmStatusAtomicRollBackFailed;
+				}
+
+			cmd=cmd->iNext;
+			}		
+		}
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::CheckResultsRef()
+// Check if this fetch has came inside atomc
+// ---------------------------------------------------------------------------
+TBool CNSmlDmCommandBuffer::CheckResultsRef(TInt aResultsRef)
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	while(cmd!=0)
+		{
+		if(aResultsRef==cmd->iResultsRef)
+			{
+			return ETrue;
+			}
+		cmd=cmd->iNext;
+		}
+	return EFalse;
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::CheckStatusRef()
+// Check if this command has came inside atomc
+// ---------------------------------------------------------------------------
+TBool CNSmlDmCommandBuffer::CheckStatusRef(TInt aStatusRef)
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	while(cmd!=0)
+		{
+		if(aStatusRef==cmd->iStatusRef)
+			{
+			return ETrue;
+			}
+		cmd=cmd->iNext;
+		}
+	return EFalse;
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::SetResultsL( TInt aResultsRef,
+// 	const CBufBase& aObject,
+// 	const TDesC8& aType,
+// 	const TDesC8& aFormat )
+// Set Results to buffer for later returning
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::SetResultsL( TInt aResultsRef,
+	const CBufBase& aObject,
+	const TDesC8& /*aType*/,
+	const TDesC8& aFormat )
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	while(cmd!=0)
+		{
+		if(aResultsRef==cmd->iResultsRef)
+			{
+			cmd->iFormat = aFormat.AllocL();
+			if(cmd->iResult)
+				{
+				cmd->iResult->Reset();
+				}
+			else
+				{
+				cmd->iResult = CBufFlat::NewL(32);
+				}
+			cmd->iResult->InsertL(0,CONST_CAST(CBufBase&, aObject).Ptr(0),
+				aObject.Size());
+			return;
+			}
+		cmd=cmd->iNext;
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::SetStatusL(TInt aStatusRef, TInt aStatusCode)
+// Set Status to buffer for later returning
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::SetStatus(TInt aStatusRef, TInt aStatusCode)
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+	if(aStatusCode>KNSmlDmStatusLargestOK)
+		{
+		iAtomicFailed = ETrue;
+		}
+	while(cmd!=0)
+		{
+		if(iAtomicFailed&&!cmd->iGotStatus)
+			{
+			cmd->iGotStatus = ETrue;
+			cmd->iStatusCode = KNSmlDmStatusNotExecuted;
+			}
+		if(aStatusRef==cmd->iStatusRef)
+			{
+			cmd->iGotStatus = ETrue;
+			cmd->iStatusCode = aStatusCode;
+			}
+		cmd=cmd->iNext;
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::SendStatusAndResultCodesL()
+// Send the results and status codes from the buffer
+// ---------------------------------------------------------------------------
+void CNSmlDmCommandBuffer::SendStatusAndResultCodesL()
+	{
+	CNSmlDmCommands* cmd=iCommandBuffer;
+
+	while(cmd!=0)
+		{
+		if(cmd->iCmdType==EAclGet && cmd->iStatusCode>0 &&
+			cmd->iStatusCode<KNSmlDmStatusLargestOK)
+			{
+			iDmModule.DoSetResultsL(cmd->iResultsRef,*cmd->iResult,
+				*cmd->iType,*cmd->iFormat,cmd->iResult->Size(),ETrue);
+			}
+		iDmModule.DoSetStatusL(cmd->iStatusRef,cmd->iStatusCode,ETrue);
+		cmd=cmd->iNext;
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::ParentNodeDeletedL()
+// Checks if parent node has been deleted
+// ---------------------------------------------------------------------------
+TBool CNSmlDmCommandBuffer::ParentNodeDeletedL(const TDesC8& aURI)
+	{
+	
+	HBufC8* uri = NSmlDmURI::RemoveProp(aURI).AllocLC();
+	TPtr8 uriPtr = uri->Des();
+	
+	while(uriPtr.Length()!=0)
+		{
+
+		CNSmlDmCommands* cmd=iCommandBuffer;
+
+		while(cmd!=0)
+			{
+			if(cmd->iCallback&&cmd->iCallback->GetStatusL()==KNSmlDmStatusOK)
+				{
+				if(cmd->iURI->Compare(uriPtr)==0)
+					{
+					CleanupStack::PopAndDestroy(); //uri
+					return ETrue;
+					}
+				}
+			cmd=cmd->iNext;
+			}
+		uriPtr = NSmlDmURI::RemoveLastSeg(uriPtr);
+		}
+	CleanupStack::PopAndDestroy(); //uri
+	return EFalse;
+	}
+
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommandBuffer::AtomicFailed()
+// Checks if some command has failed or status missing inside the atomic
+// ---------------------------------------------------------------------------
+TBool CNSmlDmCommandBuffer::AtomicFailed()
+	{
+		
+	TBool isnestedget =	IsGetWithAtomic();
+	if(isnestedget)
+	  return ETrue;
+	if(iAtomicFailed)
+		{
+		return ETrue;
+		}
+	else
+		{
+		CNSmlDmCommands* cmd=iCommandBuffer;
+		while(cmd!=0)
+			{
+			if(!cmd->iGotStatus)
+				{
+				return ETrue;
+				}
+			cmd=cmd->iNext;
+			}
+		}
+	return EFalse;
+	}
+	
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommands::CNSmlDmCommands
+// Constructor
+// ---------------------------------------------------------------------------
+CNSmlDmCommands::CNSmlDmCommands()
+	{
+	iStatusCode=KNSmlDmStatusNotExecuted;
+	}
+
+// ---------------------------------------------------------------------------
+// CNSmlDmCommands::~CNSmlDmCommands
+// Destructor
+// ---------------------------------------------------------------------------
+CNSmlDmCommands::~CNSmlDmCommands()
+	{
+	delete iURI;
+	delete iTargetURI;
+	delete iResult;
+	delete iObject;
+	delete iType;
+	delete iFormat;
+	delete iCallback;
+	}
+