diff -r 000000000000 -r b497e44ab2fc syncmlfw/dm/treemodule/src/nsmldmcommandbuffer.cpp --- /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->iStatusCodeiStatusCode = 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->iStatusCodeiResultsRef,*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; + } +