--- /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 <elements/nm_messages_base.h>
+#include <elements/nm_messages_peer.h>
+#include <elements/nm_messages_child.h>
+#include <elements/nm_messages_errorrecovery.h>
+
+
+#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<TEBase::TError>(&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<TEBase::TNull>();
+ }
+
+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<TEPeer::TLeaveRequest>())
+ {
+ 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<TEBase::TCancel>())
+ {
+ //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<TEPeer::TLeaveComplete>())
+ {
+ 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<TEChild::TDestroy>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingCancel, NetStateMachine::MState, TContext)
+EXPORT_C TBool TAwaitingCancel::Accept()
+ {
+ return iContext.iMessage.IsMessage<TEBase::TCancel>();
+ }
+
+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<TEErrorRecovery::TErrorRecoveryResponse>();
+ if (!match
+ && iContext.iMessage.IsMessage<TEBase::TError>()
+ && address_cast<const TNodeCtxId>(&iContext.iRecipient))
+ {
+ match = address_cast<const TNodeCtxId>(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<TEBase::TError>(&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<TEBase::TError>(&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<TEBase::TError>(), User::Panic(KSpecAssert_ElemMeshMachStaC, 4));
+ TEBase::TError* msg = message_cast<TEBase::TError>(&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);
+ }
+