diff -r 000000000000 -r dfb7c4ff071f commsfwsupport/commselements/meshmachine/src/mm_states.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwsupport/commselements/meshmachine/src/mm_states.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,283 @@ +// 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: +// + +/** + @file +*/ + +#include "mm_states.h" +#include "mm_activities.h" +#include +#include +#include +#include + + +#ifdef _DEBUG +// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module +// (if it could happen through user error then you should give it an explicit, documented, category + code) +_LIT(KSpecAssert_ElemMeshMachStaC, "ElemMeshMachStaC"); +#endif + +using namespace MeshMachine; +using namespace Messages; + +//-========================================================= +// +//Panics +// +//-========================================================= +#ifdef _DEBUG + _LIT (KMMStatePanic,"MMStatePanic"); +#endif + +enum + { + EPanicNoPeerPresent = 1, + KPanicNoActivity = 2 + }; + +//-========================================================= +// +//Commonly used states +// +//-========================================================= + +EXPORT_C TBool AAcceptErrorState::Accept(TNodeContextBase& aContext, TBool aSuperAccept) + { + TEBase::TError* msg = message_cast(&aContext.iMessage); + if (msg && aSuperAccept == EFalse && aContext.iNodeActivity != NULL) + { + aContext.iNodeActivity->SetError(msg->iValue); + return ETrue; + } + return aSuperAccept; + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingNull, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingNull::Accept() + { + return iContext.iMessage.IsMessage(); + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingAny, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingAny::Accept() + { + return ETrue; + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingClientLeavingRequest, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingClientLeavingRequest::Accept() + { + if (!iContext.iMessage.IsMessage()) + { + return EFalse; + } + + //TClientLeavingRequest is a "peer" message. + //You must not allow your "noPeerIds" table to include it. + __ASSERT_DEBUG(iContext.Node().FindClient(iContext.iSender), User::Panic(KMMStatePanic, EPanicNoPeerPresent)); + return ETrue; + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingLeaveComplete, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingLeaveComplete::Accept() + { + //Requests that have been posted and require this response (i.e. TDestroy + //or TLeaveRequest) are never cancellable and must complete. + //The activity must however be informed about the cancellation and take + //proper steps (if required) after the TLeaveComplete has been received. + if (iContext.iMessage.IsMessage()) + { + //For "single triple" activities with no activity object we will never receive TCancel + //because of "one shot" completion. + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + iContext.iNodeActivity->SetError(KErrCancel); + iContext.iMessage.ClearMessageId(); + return EFalse; + } + + if (!iContext.iMessage.IsMessage()) + { + return EFalse; + } + + //This is TLeaveComplete which is always being awaited for in a running activity. + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + TInt error = iContext.iNodeActivity->Error(); + + //The activity could be operating in the error mode that as resulted from + //unsuccessful addition of the peer to the iClients array. + __ASSERT_DEBUG(iContext.iPeer || error, User::Panic(KMMStatePanic, EPanicNoPeerPresent)); + + //If this assert fires - check your implementations - they are not safe. + //You _must_ mark client as leaving after sending it the leaving request. + __ASSERT_DEBUG(error || iContext.iPeer->Flags() & TClientType::ELeaving, User::Panic(KMMStatePanic, EPanicNoPeerPresent)); + + if (iContext.iPeer) + { + iContext.Node().RemoveClient(iContext.iSender, iContext); + } + return ETrue; + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingDestroy, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingDestroy::Accept() + { + return iContext.iMessage.IsMessage(); + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingCancel, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingCancel::Accept() + { + return iContext.iMessage.IsMessage(); + } + +EXPORT_DEFINE_SMELEMENT(TAwaitingErrorRecoveryResponseOrError, NetStateMachine::MState, TContext) +EXPORT_C TBool TAwaitingErrorRecoveryResponseOrError::Accept() + { + //Awaiting TErrorRecoveryResponse or TError in case there was no error recovery activity + //on the MCpr willing to accept our TErrorRecoveryRequest. + //In case of TError it is crutial to check if the message is adressed to our activity. + //There could be any other TError message coming to the node since we sent TErrorRecoveryRequest. + //And because of TErrorRecoveryRequest's forwarding, the SetSentTo is set to NULL, so this state + //will be presented with all of the potential TError messages. + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + TBool match = iContext.iMessage.IsMessage(); + if (!match + && iContext.iMessage.IsMessage() + && address_cast(&iContext.iRecipient)) + { + match = address_cast(iContext.iRecipient).NodeCtx()==iContext.ActivityId(); + } + return match; + } + +//-========================================================= +// +//Commonly used state forks +// +//-========================================================= + +EXPORT_C TInt AErrorTagOr::TransitionTag(TNodeContextBase& aContext) + { + if (aContext.iNodeActivity->Error()!=KErrNone) + { + return KErrorTag; + } + TEBase::TError* msg = message_cast(&aContext.iMessage); + if (msg) + { + aContext.iNodeActivity->SetError(msg->iValue); + return KErrorTag; + } + return 0; + } + +EXPORT_DEFINE_SMELEMENT(TNoTag, NetStateMachine::MStateFork, TContext) + +EXPORT_DEFINE_SMELEMENT(TErrorTag, NetStateMachine::MStateFork, TContext) +EXPORT_C TInt TErrorTag::TransitionTag() + { + return KErrorTag | NetStateMachine::EForward; + } + +EXPORT_DEFINE_SMELEMENT(TNoTagBackward, NetStateMachine::MStateFork, TContext) +EXPORT_C TInt TNoTagBackward::TransitionTag() + { + return KNoTag | NetStateMachine::EBackward; + } + +EXPORT_DEFINE_SMELEMENT(TNoTagOrErrorTag, NetStateMachine::MStateFork, TContext) +EXPORT_C TInt TNoTagOrErrorTag::TransitionTag() + { + TEBase::TError* msg = message_cast(&iContext.iMessage); + if (KErrNone==iContext.iNodeActivity->Error() && NULL==msg) + { + return KNoTag | NetStateMachine::EForward; + } + if (msg) + { + iContext.iNodeActivity->SetError(msg->iValue); + } + return KErrorTag | NetStateMachine::EForward; + } + +//-========================================================= +// +// Commonly used transitions +// +//-========================================================= + +EXPORT_DEFINE_SMELEMENT(TDoNothing, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TDoNothing::DoL() + { + } + +EXPORT_DEFINE_SMELEMENT(TSetIdle, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TSetIdle::DoL() + { + iContext.iNodeActivity->SetIdle(); + } + +EXPORT_DEFINE_SMELEMENT(TRemoveClient, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TRemoveClient::DoL() + { + __ASSERT_DEBUG(iContext.iPeer, User::Panic(KMMStatePanic, EPanicNoPeerPresent)); //Must be present now. + iContext.Node().RemoveClient(iContext.iSender, iContext); + } + +EXPORT_DEFINE_SMELEMENT(TRaiseActivityError, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TRaiseActivityError::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + TInt err = iContext.iNodeActivity->Error(); + __ASSERT_DEBUG(err != KErrNone, User::Panic(KSpecAssert_ElemMeshMachStaC, 1)); + User::Leave(err); + } + +EXPORT_DEFINE_SMELEMENT(TRaiseAndClearActivityError, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TRaiseAndClearActivityError::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + TInt err = iContext.iNodeActivity->Error(); + __ASSERT_DEBUG(err != KErrNone, User::Panic(KSpecAssert_ElemMeshMachStaC, 2)); + iContext.iNodeActivity->SetError(KErrNone); + User::Leave(err); + } + +EXPORT_DEFINE_SMELEMENT(TStoreError, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TStoreError::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ElemMeshMachStaC, 3)); + __ASSERT_DEBUG(iContext.iMessage.IsMessage(), User::Panic(KSpecAssert_ElemMeshMachStaC, 4)); + TEBase::TError* msg = message_cast(&iContext.iMessage); + iContext.iNodeActivity->SetError(msg->iValue); + } + +EXPORT_DEFINE_SMELEMENT(TClearError, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TClearError::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + iContext.iNodeActivity->SetError(KErrNone); + } + +EXPORT_DEFINE_SMELEMENT(TForwardMessageToOriginators, NetStateMachine::MStateTransition, TContext) +EXPORT_C void TForwardMessageToOriginators::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity)); + iContext.iNodeActivity->PostToOriginators(iContext.iMessage); + } +