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 { |