commsfwsupport/commselements/meshmachine/src/mm_states.cpp
changeset 0 dfb7c4ff071f
--- /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);
+	}
+