commsfwsupport/commselements/meshmachine/src/mm_activities.cpp
branchRCL_3
changeset 18 9644881fedd0
parent 11 98a7181d2ce7
equal deleted inserted replaced
17:9ddb1d67ebaf 18:9644881fedd0
    43 //-=========================================================
    43 //-=========================================================
    44 _LIT (KMMActivityPanic,"MMActivityPanic");
    44 _LIT (KMMActivityPanic,"MMActivityPanic");
    45 enum
    45 enum
    46 	{
    46 	{
    47 	EPanicCorruptedContext = 1,
    47 	EPanicCorruptedContext = 1,
    48 	EPanicNoPreallocatedSpace = 2
    48 	EPanicNoPreallocatedSpace = 2,
       
    49 	EPanicOutOfActivities = 3,
       
    50 	EPanicOutOfBounds
    49 	};
    51 	};
    50 
    52 
    51 //-=========================================================
    53 //-=========================================================
    52 //
    54 //
    53 //TNodeActivityIter
    55 //TNodeActivityIter
   165     //The role of this method is to filter out all messages that 'this' should
   167     //The role of this method is to filter out all messages that 'this' should
   166     //not be bothered with. 'this' should be interested in messages coming from
   168     //not be bothered with. 'this' should be interested in messages coming from
   167     //what's set as iPostedToId or from one of the orginators. 
   169     //what's set as iPostedToId or from one of the orginators. 
   168     //if the message's recipient specifies the activity id, then that
   170     //if the message's recipient specifies the activity id, then that
   169     //activity must much that of 'this'.
   171     //activity must much that of 'this'.
   170     TBool sender = iPostedToId.IsNull() || 
   172     TBool sender = PostedToNodeId().IsNull() || 
   171     			   aContext.iSender == iPostedToId || 
   173     			   aContext.iSender == PostedToNodeId() || 
   172     			   FindOriginator(aContext.iSender) != KErrNotFound;
   174     			   FindOriginator(aContext.iSender) != KErrNotFound;
   173     const TNodeCtxId* recipient = address_cast<const TNodeCtxId>(&aContext.iRecipient);
   175     const TNodeCtxId* recipient = address_cast<const TNodeCtxId>(&aContext.iRecipient);
   174     TBool activity = (recipient == NULL || ActivityId() == recipient->NodeCtx());
   176     TBool activity = (recipient == NULL || ActivityId() == recipient->NodeCtx());
   175 
   177 
   176 #ifdef SYMBIAN_TRACE_ENABLE
   178 #ifdef SYMBIAN_TRACE_ENABLE
   179 		{
   181 		{
   180 		NM_LOG_START_BLOCK(KMeshMachineSubTag, _L8("CNodeActivityBase::MatchSender"));
   182 		NM_LOG_START_BLOCK(KMeshMachineSubTag, _L8("CNodeActivityBase::MatchSender"));
   181 		if(!sender)
   183 		if(!sender)
   182 			{
   184 			{
   183 			MESH_LOG((KMeshMachineSubTag(), _L8("CNodeActivityBase %08x:\tiPostedToId mismatch:"), this));
   185 			MESH_LOG((KMeshMachineSubTag(), _L8("CNodeActivityBase %08x:\tiPostedToId mismatch:"), this));
   184 			NM_LOG_ADDRESS(KMeshMachineSubTag(), iPostedToId);
   186 			NM_LOG_ADDRESS(KMeshMachineSubTag(), PostedToNodeId());
   185 			NM_LOG_ADDRESS(KMeshMachineSubTag(), aContext.iSender);
   187 			NM_LOG_ADDRESS(KMeshMachineSubTag(), aContext.iSender);
   186 			MESH_LOG((KMeshMachineSubTag(), _L8("CNodeActivityBase %08x:\toriginators' mismatch:"), this));
   188 			MESH_LOG((KMeshMachineSubTag(), _L8("CNodeActivityBase %08x:\toriginators' mismatch:"), this));
   187 			for (TInt i = iOriginators.Count() - 1; i>=0; i--)
   189 			for (TInt i = iOriginators.Count() - 1; i>=0; i--)
   188 		        {
   190 		        {
   189 		        NM_LOG_ADDRESS(KMeshMachineSubTag(), iOriginators[i].RecipientId());
   191 		        NM_LOG_ADDRESS(KMeshMachineSubTag(), iOriginators[i].RecipientId());
   315     return nextRet;
   317     return nextRet;
   316 	}
   318 	}
   317 
   319 
   318 EXPORT_C void CNodeActivityBase::Cancel(TNodeContextBase& aContext)
   320 EXPORT_C void CNodeActivityBase::Cancel(TNodeContextBase& aContext)
   319 	{//we expect KErrCancel be set as a result of the state cancelation
   321 	{//we expect KErrCancel be set as a result of the state cancelation
   320     MESH_LOG((KMeshMachineSubTag, _L8("CNodeActivityBase %08x:\tCancel(), iPostedToId %08x"), this, iPostedToId.Ptr() ? &iPostedToId.Node() : NULL));
   322     MESH_LOG((KMeshMachineSubTag, _L8("CNodeActivityBase %08x:\tCancel(), PostedToNodeId %08x"), this, PostedToNodeId().Ptr()));
   321 
   323 
   322 	if (!iPostedToId.IsNull())
   324 	if ((PostedToPeer() && !(PostedToPeer()->Flags() & TClientType::ELeaving)) ||
   323 		{
   325 	     PostedToNodeId() == aContext.Node().Id())
   324 		RClientInterface::OpenPostMessageClose(TNodeCtxId(ActivityId(), iNode.Id()), iPostedToId, TEBase::TCancel().CRef());
   326 		{//only safe to forward TCancels to non-leavers or self. There is an underlying assumption that a node won't dissapear in presence of activities (see AMMNodeBase::~AMMNodeBase)
       
   327 		RClientInterface::OpenPostMessageClose(TNodeCtxId(ActivityId(), iNode.Id()), PostedToNodeId(), TEBase::TCancel().CRef());
   325 		}
   328 		}
   326     else
   329     else
   327         {
   330         {
   328     	NetStateMachine::ACore::Cancel(&aContext);
   331     	NetStateMachine::ACore::Cancel(&aContext);
   329         }
   332         }
   350 	for (TInt n = iOriginators.Count() - 1;n>=0; n--)
   353 	for (TInt n = iOriginators.Count() - 1;n>=0; n--)
   351 		{
   354 		{
   352 		if (PostToOriginator(iOriginators[n], aMessage))
   355 		if (PostToOriginator(iOriginators[n], aMessage))
   353 			{
   356 			{
   354 			++msgSendCount;
   357 			++msgSendCount;
   355 	    	iOriginators[n].Peer().SetFlags(aFlagsToSet);
   358 	    	iOriginators[n].SetFlags(aFlagsToSet);
   356 	    	iOriginators[n].Peer().ClearFlags(aFlagsToClear);
   359 	    	iOriginators[n].ClearFlags(aFlagsToClear);
   357 			};
   360 			};
   358 		}
   361 		}
   359 	return msgSendCount;
   362 	return msgSendCount;
   360 	}
   363 	}
   361 
   364 
   362 EXPORT_C void CNodeActivityBase::SetPostedTo(const TNodeId& aNodeId)
   365 EXPORT_C void CNodeActivityBase::SetPostedTo(const TNodeId& aNodeId)
   363     {
   366     {
   364     iPostedToId = aNodeId;
   367     //You are being punished for storing a postedto TNodeId that you also know as your peer.
       
   368     //the Messages::RNodeInterface& overload of CNodeActivityBase::SetPostedTo
       
   369     //It is dangerous to use this overload for peers when the relation with these peers
       
   370     //is being terminated. the PostedTo facility is also used to forward TCancel in
       
   371     //the automatic calencallation handling. No message can be posted to a leaving peer
       
   372     //but only peers (Messages::RNodeInterfaces) can be recognised as leaving. 
       
   373     //
       
   374     //ASSERT temporarily commened out as it is a behavioural break. A Polonium BR
       
   375     //has been drafted and will be raised when the RNodeInterface overloads end up in the
       
   376     //codeline. http://polonium.ext.nokia.com/changerequests/cr/601/
       
   377     //__ASSERT_DEBUG(iNode.FindClient(aNodeId) == NULL, User::Panic(KSpecAssert_ElemMeshMachActC, 14));     
       
   378     
       
   379     if (aNodeId == Messages::TNodeId::NullId())
       
   380         {
       
   381         ClearPostedTo();
       
   382         return;
       
   383         }
       
   384     iPostedToId.Open(aNodeId);
       
   385     }
       
   386 
       
   387 EXPORT_C void CNodeActivityBase::SetPostedTo(const Messages::RNodeInterface& aRecepient)
       
   388     {
       
   389     iPostedToId.Open(aRecepient);
   365     }
   390     }
   366 
   391 
   367 EXPORT_C void CNodeActivityBase::ClearPostedTo()
   392 EXPORT_C void CNodeActivityBase::ClearPostedTo()
   368     {
   393     {
   369     iPostedToId.SetNull();
   394     iPostedToId.Close();
       
   395     }
       
   396 
       
   397 EXPORT_C const Messages::TNodeId& CNodeActivityBase::PostedToNodeId() const
       
   398     {
       
   399     return iPostedToId.NodeId();
       
   400     }
       
   401 
       
   402 EXPORT_C const Messages::RNodeInterface* CNodeActivityBase::PostedToPeer() const
       
   403     {
       
   404     return iPostedToId.Peer();
   370     }
   405     }
   371 
   406 
   372 EXPORT_C void CNodeActivityBase::PostRequestTo(const RNodeInterface& aRecipient, const TSignalBase& aMessage, const TBool aRecipientIdCritical)
   407 EXPORT_C void CNodeActivityBase::PostRequestTo(const RNodeInterface& aRecipient, const TSignalBase& aMessage, const TBool aRecipientIdCritical)
   373 	{
   408 	{
   374 	aRecipient.PostMessage(TNodeCtxId(ActivityId(), iNode.Id()), aMessage);
   409 	aRecipient.PostMessage(TNodeCtxId(ActivityId(), iNode.Id()), aMessage);
   375 
   410 
   376 	// Provide the option for the identity of the receipient to be unimportant when the response arrives
   411 	// Provide the option for the identity of the receipient to be unimportant when the response arrives
   377 	iPostedToId = aRecipientIdCritical ? aRecipient.RecipientId() : TNodeId::NullId();
   412 	ClearPostedTo();
       
   413     if (aRecipientIdCritical)
       
   414         {
       
   415         SetPostedTo(aRecipient);
       
   416         }
   378 	}
   417 	}
   379 
   418 
   380 //Avoid using this function, always prefer PostRequestTo(const RNodeInterface& aRecipient, const TNodeSignal& aMessage)
   419 //Avoid using this function, always prefer PostRequestTo(const RNodeInterface& aRecipient, const TNodeSignal& aMessage)
   381 EXPORT_C void CNodeActivityBase::PostRequestTo(const TNodeId& aRecipient, const TSignalBase& aMessage, const TBool aRecipientIdCritical)
   420 EXPORT_C void CNodeActivityBase::PostRequestTo(const TNodeId& aRecipient, const TSignalBase& aMessage, const TBool aRecipientIdCritical)
   382 	{
   421 	{
   383 	RClientInterface::OpenPostMessageClose(TNodeCtxId(ActivityId(), iNode.Id()), aRecipient, aMessage);
   422 	RClientInterface::OpenPostMessageClose(TNodeCtxId(ActivityId(), iNode.Id()), aRecipient, aMessage);
   384 
   423 
   385 	// Provide the option for the identity of the receipient to be unimportant when the response arrives
   424 	// Provide the option for the identity of the receipient to be unimportant when the response arrives
   386 	iPostedToId = aRecipientIdCritical ? aRecipient : TNodeId::NullId();
   425 	ClearPostedTo();
       
   426 	if (aRecipientIdCritical)
       
   427 	    {
       
   428         SetPostedTo(aRecipient);
       
   429 	    }
   387 	}
   430 	}
   388 
   431 
   389 EXPORT_C TBool CNodeActivityBase::IsIdle() const
   432 EXPORT_C TBool CNodeActivityBase::IsIdle() const
   390 	{
   433 	{
   391 	return NetStateMachine::ACore::IsIdle();
   434 	return NetStateMachine::ACore::IsIdle();
   415 			RemoveOriginator(n); //Do not allow ~CNodeActivityBase to post as client's might be already gone
   458 			RemoveOriginator(n); //Do not allow ~CNodeActivityBase to post as client's might be already gone
   416 			}
   459 			}
   417         }
   460         }
   418     }
   461     }
   419 
   462 
       
   463 
       
   464 
       
   465 
       
   466 //-=========================================================
       
   467 //
       
   468 //CNodeActivityBase::RPostedToNodeOrPeer
       
   469 //
       
   470 //-=========================================================
       
   471 CNodeActivityBase::RPostedToNodeOrPeer::RPostedToNodeOrPeer() 
       
   472     {
       
   473     Close();
       
   474     }
       
   475 
       
   476 void CNodeActivityBase::RPostedToNodeOrPeer::Open(const Messages::RNodeInterface& aPeer)
       
   477     {
       
   478     Close();
       
   479     *_Peer() = const_cast<Messages::RNodeInterface*>(&aPeer);
       
   480     }
       
   481 
       
   482 void CNodeActivityBase::RPostedToNodeOrPeer::Open(const Messages::TNodeId& aNode)
       
   483     {
       
   484     __ASSERT_DEBUG(aNode.Ptr(), User::Panic(KSpecAssert_ElemMeshMachActC, 15));    
       
   485     //see Messages::TNodeId::operator= (snapping size is essential in case aNode is more than just plain TNodeId).
       
   486     *_Node() = Messages::TNodeId(); 
       
   487     
       
   488     //normal assigment
       
   489     *_Node() = aNode;
       
   490     }
       
   491 void CNodeActivityBase::RPostedToNodeOrPeer::Close()
       
   492     {
       
   493     Mem::FillZ(iBuf, sizeof(iBuf));
       
   494     }
       
   495 
       
   496 const Messages::RNodeInterface* CNodeActivityBase::RPostedToNodeOrPeer::Peer() const
       
   497     {
       
   498     return _Node()->Ptr() ? NULL : *_Peer();
       
   499     }
       
   500 const Messages::TNodeId& CNodeActivityBase::RPostedToNodeOrPeer::NodeId() const
       
   501     {
       
   502     return (_Node()->Ptr() ? *_Node() : (*_Peer() ? (*_Peer())->RecipientId() : Messages::TNodeId::NullId()));
       
   503     }
       
   504 
       
   505 
   420 //-=========================================================
   506 //-=========================================================
   421 //
   507 //
   422 //CNodeRetryActivity
   508 //CNodeRetryActivity
   423 //
   509 //
   424 //-=========================================================
   510 //-=========================================================
   459 EXPORT_C void CNodeRetryActivity::ReturnInterfacePtrL(AActivitySemaphore*& aInterface)
   545 EXPORT_C void CNodeRetryActivity::ReturnInterfacePtrL(AActivitySemaphore*& aInterface)
   460     {
   546     {
   461     aInterface = this;
   547     aInterface = this;
   462     }
   548     }
   463 
   549 
       
   550 // BitMap utility used only by CNodeParallelActivityBase::GetNextActivityCount
       
   551 template<TInt SIZE>
       
   552 class TBitmap {
       
   553 public:
       
   554     static const TInt iSize = sizeof(TUint32) * 8;
       
   555     static const TUint32 iSizeMask = iSize - 1;
       
   556     static const TUint32 iFull = ~0;
       
   557     static const TInt iCount = (SIZE + iSizeMask) / iSize;
       
   558     TBitmap();
       
   559     void SetBit(TUint aBitNum);
       
   560     TInt GetFreeBit() const;
       
   561 
       
   562 private:
       
   563     TUint32 iBits[iCount];
       
   564 };
       
   565 
       
   566 template<TInt SIZE>
       
   567 TBitmap<SIZE>::TBitmap()
       
   568 {
       
   569     for (TInt i = 0 ; i < iCount ; ++i)
       
   570         {
       
   571         iBits[i] = 0;
       
   572         }
       
   573 }
       
   574 
       
   575 template<TInt SIZE>
       
   576 void TBitmap<SIZE>::SetBit(TUint aBitNum)
       
   577     {
       
   578     const TInt index = aBitNum / iSize;
       
   579 	__ASSERT_ALWAYS(index < iCount,User::Panic(KMMActivityPanic,EPanicOutOfBounds));
       
   580 
       
   581     iBits[index] |= 1 << (aBitNum & iSizeMask);
       
   582     }
       
   583 
       
   584 template<TInt SIZE>
       
   585 TInt TBitmap<SIZE>::GetFreeBit() const
       
   586     {
       
   587     for (TInt i = 0 ; i < iCount ; ++i)
       
   588         {
       
   589         const TUint32 bits = iBits[i];
       
   590         if (bits != iFull)
       
   591             {
       
   592 			// Bitmap represents list of activity IDs. Activity ID 1 is a reserved value.
       
   593 			// In order to mirror this fact the first bit of the bitmap is also always reserved
       
   594             TUint32 mask = 2;
       
   595             for (TInt bitIndex = 1 ; bitIndex < iSize ; ++bitIndex)
       
   596                 {
       
   597                 if ((bits & mask) == 0)
       
   598                     {
       
   599                     return (i * iSize) + bitIndex;
       
   600                     }
       
   601                 mask <<= 1;
       
   602                 }
       
   603             }
       
   604         }
       
   605     return KErrNotFound;
       
   606     }
       
   607 
       
   608 
   464 //-=========================================================
   609 //-=========================================================
   465 //
   610 //
   466 //CNodeParallelActivityBase
   611 //CNodeParallelActivityBase
   467 //
   612 //
   468 //-=========================================================
   613 //-=========================================================
   469 // For custom activities to implement NewL
   614 
   470 EXPORT_C TUint CNodeParallelActivityBase::GetNextActivityCountL( const TNodeActivity& aActivitySig, const AMMNodeBase& aNode )
   615 
   471 	{
   616 // For custom activities to implement New
   472 	TInt c = 1, i = 0;
   617 EXPORT_C TUint CNodeParallelActivityBase::GetNextActivityCount( const TNodeActivity& aActivitySig, const AMMNodeBase& aNode )
       
   618 	{
       
   619 	TInt c = 1;
   473 	
   620 	
   474 	const RPointerArray<CNodeActivityBase>& activities = aNode.Activities();
   621 	const RPointerArray<CNodeActivityBase>& activities = aNode.Activities();
   475 	RArray<TInt> activityids;
   622 	
   476 	CleanupClosePushL(activityids);
   623 	TBitmap<256> activityids;
   477 
       
   478 	// collect the currently used ids
   624 	// collect the currently used ids
   479 	for (TInt i = 0; i < activities.Count(); i++)
   625 	for (TInt i = 0; i < activities.Count(); i++)
   480 		{
   626 		{
   481 		TInt16 id = activities[i]->ActivityId();
   627 		TInt16 id = activities[i]->ActivityId();
   482 		if ((id&0xff) == aActivitySig.iId)
   628 		if ((id&0xff) == aActivitySig.iId)
   483 			{
   629 			{
   484 			TInt8 uniqueid = id >> 8;
   630 			TInt8 uniqueid = id >> 8;
   485 			activityids.InsertInOrderL(uniqueid);
   631 			activityids.SetBit(uniqueid);
   486 			}
   632 			}
   487 		}
   633 		}
   488 
   634 	c = activityids.GetFreeBit();
   489 	// find first available.
   635 	
   490 	while (i < activityids.Count()
   636 	__ASSERT_ALWAYS(c>=0,User::Panic(KMMActivityPanic,EPanicOutOfActivities));
   491           && activityids[i] == c)
       
   492 		{
       
   493 		++i;
       
   494 		++c;
       
   495 		}
       
   496 	CleanupStack::PopAndDestroy(&activityids);
       
   497 
       
   498 	if(c > KActivityParallelRangeMax>>8)
       
   499 		{
       
   500 		User::Leave(KErrInUse);
       
   501 		}
       
   502     return c;
   637     return c;
   503 	}
   638 	}
   504 
   639 
   505 EXPORT_C CNodeActivityBase* CNodeParallelActivityBase::NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode )
   640 EXPORT_C CNodeActivityBase* CNodeParallelActivityBase::NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode )
   506     {
   641     {