--- /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;
+ }
+