commsfwsupport/commselements/meshmachine/src/mm_states.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18 */
       
    19 
       
    20 #include "mm_states.h"
       
    21 #include "mm_activities.h"
       
    22 #include <elements/nm_messages_base.h>
       
    23 #include <elements/nm_messages_peer.h>
       
    24 #include <elements/nm_messages_child.h>
       
    25 #include <elements/nm_messages_errorrecovery.h>
       
    26 
       
    27 
       
    28 #ifdef _DEBUG
       
    29 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    30 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    31 _LIT(KSpecAssert_ElemMeshMachStaC, "ElemMeshMachStaC");
       
    32 #endif
       
    33 
       
    34 using namespace MeshMachine;
       
    35 using namespace Messages;
       
    36 
       
    37 //-=========================================================
       
    38 //
       
    39 //Panics
       
    40 //
       
    41 //-=========================================================
       
    42 #ifdef _DEBUG
       
    43 	_LIT (KMMStatePanic,"MMStatePanic");
       
    44 #endif
       
    45 
       
    46 enum
       
    47 	{
       
    48 	EPanicNoPeerPresent = 1,
       
    49 	KPanicNoActivity = 2
       
    50 	};
       
    51 
       
    52 //-=========================================================
       
    53 //
       
    54 //Commonly used states
       
    55 //
       
    56 //-=========================================================
       
    57 
       
    58 EXPORT_C TBool AAcceptErrorState::Accept(TNodeContextBase& aContext, TBool aSuperAccept)
       
    59 	{
       
    60 	TEBase::TError* msg = message_cast<TEBase::TError>(&aContext.iMessage);
       
    61 	if (msg && aSuperAccept == EFalse && aContext.iNodeActivity != NULL)
       
    62     	{
       
    63     	aContext.iNodeActivity->SetError(msg->iValue);
       
    64 		return ETrue;
       
    65 		}
       
    66 	return aSuperAccept;
       
    67 	}
       
    68 
       
    69 EXPORT_DEFINE_SMELEMENT(TAwaitingNull, NetStateMachine::MState, TContext)
       
    70 EXPORT_C TBool TAwaitingNull::Accept()
       
    71 	{
       
    72 	return iContext.iMessage.IsMessage<TEBase::TNull>();
       
    73 	}
       
    74 
       
    75 EXPORT_DEFINE_SMELEMENT(TAwaitingAny, NetStateMachine::MState, TContext)
       
    76 EXPORT_C TBool TAwaitingAny::Accept()
       
    77 	{
       
    78 	return ETrue;
       
    79 	}
       
    80 
       
    81 EXPORT_DEFINE_SMELEMENT(TAwaitingClientLeavingRequest, NetStateMachine::MState, TContext)
       
    82 EXPORT_C TBool TAwaitingClientLeavingRequest::Accept()
       
    83 	{
       
    84 	if (!iContext.iMessage.IsMessage<TEPeer::TLeaveRequest>())
       
    85     	{
       
    86     	return EFalse;
       
    87     	}
       
    88 
       
    89 	//TClientLeavingRequest is a "peer" message.
       
    90 	//You must not allow your "noPeerIds" table to include it.
       
    91 	__ASSERT_DEBUG(iContext.Node().FindClient(iContext.iSender), User::Panic(KMMStatePanic, EPanicNoPeerPresent));
       
    92 	return ETrue;
       
    93 	}
       
    94 
       
    95 EXPORT_DEFINE_SMELEMENT(TAwaitingLeaveComplete, NetStateMachine::MState, TContext)
       
    96 EXPORT_C TBool TAwaitingLeaveComplete::Accept()
       
    97 	{
       
    98 	//Requests that have been posted and require this response (i.e. TDestroy
       
    99 	//or TLeaveRequest) are never cancellable and must complete.
       
   100 	//The activity must however be informed about the cancellation and take
       
   101 	//proper steps (if required) after the TLeaveComplete has been received.
       
   102 	if (iContext.iMessage.IsMessage<TEBase::TCancel>())
       
   103 		{
       
   104 		//For "single triple" activities with no activity object we will never receive TCancel
       
   105 		//because of "one shot" completion.
       
   106 		__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   107 		iContext.iNodeActivity->SetError(KErrCancel);
       
   108 		iContext.iMessage.ClearMessageId();
       
   109 		return EFalse;
       
   110 		}
       
   111 
       
   112 	if (!iContext.iMessage.IsMessage<TEPeer::TLeaveComplete>())
       
   113     	{
       
   114     	return EFalse;
       
   115     	}
       
   116 
       
   117 	//This is TLeaveComplete which is always being awaited for in a running activity.
       
   118 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   119 	TInt error = iContext.iNodeActivity->Error();
       
   120 
       
   121 	//The activity could be operating in the error mode that as resulted from
       
   122 	//unsuccessful addition of the peer to the iClients array.
       
   123 	__ASSERT_DEBUG(iContext.iPeer || error, User::Panic(KMMStatePanic, EPanicNoPeerPresent));
       
   124 
       
   125 	//If this assert fires - check your implementations - they are not safe.
       
   126 	//You _must_ mark client as leaving after sending it the leaving request.
       
   127 	__ASSERT_DEBUG(error || iContext.iPeer->Flags() & TClientType::ELeaving, User::Panic(KMMStatePanic, EPanicNoPeerPresent));
       
   128 
       
   129 	if (iContext.iPeer)
       
   130 		{
       
   131 		iContext.Node().RemoveClient(iContext.iSender, iContext);
       
   132 		}
       
   133     return ETrue;
       
   134 	}
       
   135 
       
   136 EXPORT_DEFINE_SMELEMENT(TAwaitingDestroy, NetStateMachine::MState, TContext)
       
   137 EXPORT_C TBool TAwaitingDestroy::Accept()
       
   138 	{
       
   139 	return iContext.iMessage.IsMessage<TEChild::TDestroy>();
       
   140 	}
       
   141 
       
   142 EXPORT_DEFINE_SMELEMENT(TAwaitingCancel, NetStateMachine::MState, TContext)
       
   143 EXPORT_C TBool TAwaitingCancel::Accept()
       
   144 	{
       
   145 	return iContext.iMessage.IsMessage<TEBase::TCancel>();
       
   146 	}
       
   147 
       
   148 EXPORT_DEFINE_SMELEMENT(TAwaitingErrorRecoveryResponseOrError, NetStateMachine::MState, TContext)
       
   149 EXPORT_C TBool TAwaitingErrorRecoveryResponseOrError::Accept()
       
   150     {
       
   151     //Awaiting TErrorRecoveryResponse or TError in case there was no error recovery activity
       
   152     //on the MCpr willing to accept our TErrorRecoveryRequest.
       
   153     //In case of TError it is crutial to check if the message is adressed to our activity.
       
   154     //There could be any other TError message coming to the node since we sent TErrorRecoveryRequest.
       
   155     //And because of TErrorRecoveryRequest's forwarding, the SetSentTo is set to NULL, so this state
       
   156     //will be presented with all of the potential TError messages.
       
   157     __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   158 	TBool match = iContext.iMessage.IsMessage<TEErrorRecovery::TErrorRecoveryResponse>();
       
   159 	if (!match
       
   160 		&& iContext.iMessage.IsMessage<TEBase::TError>()
       
   161 		&& address_cast<const TNodeCtxId>(&iContext.iRecipient))
       
   162 		{
       
   163 		match = address_cast<const TNodeCtxId>(iContext.iRecipient).NodeCtx()==iContext.ActivityId();
       
   164 		}
       
   165 	return match;
       
   166     }
       
   167 
       
   168 //-=========================================================
       
   169 //
       
   170 //Commonly used state forks
       
   171 //
       
   172 //-=========================================================
       
   173 
       
   174 EXPORT_C TInt AErrorTagOr::TransitionTag(TNodeContextBase& aContext)
       
   175  	{
       
   176  	if (aContext.iNodeActivity->Error()!=KErrNone)
       
   177  		{
       
   178  		return KErrorTag;
       
   179  		}
       
   180  	TEBase::TError* msg = message_cast<TEBase::TError>(&aContext.iMessage);
       
   181     if (msg)
       
   182         {
       
   183         aContext.iNodeActivity->SetError(msg->iValue);
       
   184         return KErrorTag;
       
   185         }
       
   186  	return 0;
       
   187  	}
       
   188 
       
   189 EXPORT_DEFINE_SMELEMENT(TNoTag, NetStateMachine::MStateFork, TContext)
       
   190 
       
   191 EXPORT_DEFINE_SMELEMENT(TErrorTag, NetStateMachine::MStateFork, TContext)
       
   192 EXPORT_C TInt TErrorTag::TransitionTag()
       
   193 	{
       
   194 	return KErrorTag | NetStateMachine::EForward;
       
   195 	}
       
   196 
       
   197 EXPORT_DEFINE_SMELEMENT(TNoTagBackward, NetStateMachine::MStateFork, TContext)
       
   198 EXPORT_C TInt TNoTagBackward::TransitionTag()
       
   199 	{
       
   200 	return KNoTag | NetStateMachine::EBackward;
       
   201 	}
       
   202 
       
   203 EXPORT_DEFINE_SMELEMENT(TNoTagOrErrorTag, NetStateMachine::MStateFork, TContext)
       
   204 EXPORT_C TInt TNoTagOrErrorTag::TransitionTag()
       
   205     {
       
   206 	TEBase::TError* msg = message_cast<TEBase::TError>(&iContext.iMessage);
       
   207 	if (KErrNone==iContext.iNodeActivity->Error() && NULL==msg)
       
   208 		{
       
   209 		return KNoTag | NetStateMachine::EForward;
       
   210 		}
       
   211 	if (msg)
       
   212 		{
       
   213 		iContext.iNodeActivity->SetError(msg->iValue);
       
   214 		}
       
   215 	return KErrorTag | NetStateMachine::EForward;
       
   216     }
       
   217 
       
   218 //-=========================================================
       
   219 //
       
   220 // Commonly used transitions
       
   221 //
       
   222 //-=========================================================
       
   223 
       
   224 EXPORT_DEFINE_SMELEMENT(TDoNothing, NetStateMachine::MStateTransition, TContext)
       
   225 EXPORT_C void TDoNothing::DoL()
       
   226 	{
       
   227 	}
       
   228 
       
   229 EXPORT_DEFINE_SMELEMENT(TSetIdle, NetStateMachine::MStateTransition, TContext)
       
   230 EXPORT_C void TSetIdle::DoL()
       
   231 	{
       
   232 	iContext.iNodeActivity->SetIdle();
       
   233 	}
       
   234 
       
   235 EXPORT_DEFINE_SMELEMENT(TRemoveClient, NetStateMachine::MStateTransition, TContext)
       
   236 EXPORT_C void TRemoveClient::DoL()
       
   237 	{
       
   238 	__ASSERT_DEBUG(iContext.iPeer, User::Panic(KMMStatePanic, EPanicNoPeerPresent)); //Must be present now.
       
   239 	iContext.Node().RemoveClient(iContext.iSender, iContext);
       
   240 	}
       
   241 
       
   242 EXPORT_DEFINE_SMELEMENT(TRaiseActivityError, NetStateMachine::MStateTransition, TContext)
       
   243 EXPORT_C void TRaiseActivityError::DoL()
       
   244 	{
       
   245 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   246 	TInt err = iContext.iNodeActivity->Error();
       
   247 	__ASSERT_DEBUG(err != KErrNone, User::Panic(KSpecAssert_ElemMeshMachStaC, 1));
       
   248 	User::Leave(err);
       
   249 	}
       
   250 
       
   251 EXPORT_DEFINE_SMELEMENT(TRaiseAndClearActivityError, NetStateMachine::MStateTransition, TContext)
       
   252 EXPORT_C void TRaiseAndClearActivityError::DoL()
       
   253 	{
       
   254 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   255 	TInt err = iContext.iNodeActivity->Error();
       
   256 	__ASSERT_DEBUG(err != KErrNone, User::Panic(KSpecAssert_ElemMeshMachStaC, 2));
       
   257 	iContext.iNodeActivity->SetError(KErrNone);
       
   258 	User::Leave(err);
       
   259 	}
       
   260 
       
   261 EXPORT_DEFINE_SMELEMENT(TStoreError, NetStateMachine::MStateTransition, TContext)
       
   262 EXPORT_C void TStoreError::DoL()
       
   263 	{
       
   264 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ElemMeshMachStaC, 3));
       
   265 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TEBase::TError>(), User::Panic(KSpecAssert_ElemMeshMachStaC, 4));
       
   266 	TEBase::TError* msg = message_cast<TEBase::TError>(&iContext.iMessage);
       
   267 	iContext.iNodeActivity->SetError(msg->iValue);
       
   268 	}
       
   269 
       
   270 EXPORT_DEFINE_SMELEMENT(TClearError, NetStateMachine::MStateTransition, TContext)
       
   271 EXPORT_C void TClearError::DoL()
       
   272 	{
       
   273     __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   274 	iContext.iNodeActivity->SetError(KErrNone);
       
   275 	}
       
   276 
       
   277 EXPORT_DEFINE_SMELEMENT(TForwardMessageToOriginators, NetStateMachine::MStateTransition, TContext)
       
   278 EXPORT_C void TForwardMessageToOriginators::DoL()
       
   279 	{
       
   280     __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KMMStatePanic, KPanicNoActivity));
       
   281     iContext.iNodeActivity->PostToOriginators(iContext.iMessage);
       
   282 	}
       
   283