datacommsserver/esockserver/core_states/ss_corepractivities.cpp
changeset 40 34fc115b8742
parent 22 592244873960
child 65 41cc8e7ff496
--- a/datacommsserver/esockserver/core_states/ss_corepractivities.cpp	Thu May 27 14:07:49 2010 +0300
+++ b/datacommsserver/esockserver/core_states/ss_corepractivities.cpp	Fri Jun 11 14:52:21 2010 +0300
@@ -1604,12 +1604,20 @@
 // CommsBinderActivity and CCommsBinderCombiningActivity.
 //
 //-=========================================================
-
+// When I node need to create the data client, this mutex block if the dataclient is leaving.
+// A scenario can arise when a connection is being started, stopped and started again in succession.
+// the stop might interfere with the second start and ccause the second start to fail.
+// this mutex will ensure that the leaving DC is completely destroyed, and then the second start is continued
+// - when any of the data clients is being destroyed 
+// - when a non-leaving data client is present or the activity is already running
+//
 EXPORT_C TBool CCommsBinderActivity::TDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext)
   	{
   	TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId());
   	__ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 17)); //Diagnostic
-  	if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext))
+    TInt numOfLeavingDataClients = aContext.Node().CountClients<TDefaultClientMatchPolicy>(
+                                   /*include*/TClientType(TCFClientType::EData, TCFClientType::ELeaving));
+  	if (numOfLeavingDataClients == 0 && (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext)))
   		{
   		return EFalse;
   		}
@@ -1620,7 +1628,9 @@
   	{
   	TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId());
   	__ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 18)); //Diagnostic
-  	if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext, TCFClientType::EDefault))
+    TInt numOfLeavingDataClients = aContext.Node().CountClients<TDefaultClientMatchPolicy>(
+                                   /*include*/TClientType(TCFClientType::EData, TCFClientType::ELeaving));
+  	if (numOfLeavingDataClients == 0 && (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext, TCFClientType::EDefault)))
   		{
   		return EFalse;
   		}
@@ -1701,6 +1711,28 @@
 	iPendingBinder->SetFlags(TCFClientType::EActivating);
     }
 
+
+EXPORT_C void CCommsBinderActivity::Cancel(TNodeContextBase& aContext)
+    {
+    if (iPendingBinder)
+        {
+        //iPendingBinder is set when CCommsBinderActivity decides which of its dataclients it 
+        //wishes to send along with its TCommsBinderResponse and promptly (on the same stack) as
+        //this response is sent. After TCommsBinderResponse, the error handling of CCommsBinderActivity
+        //changes in that it should not flag any errors back to the recpient of TCommsBinderResponse.
+        //Such response may be when:
+        //(1) the recipient responds to TCommsBinderResponse with TError - the activity is finished, the recipients doesn't wait for anything (certainly not for an error)
+        //(2) the recipients explicitly cancels (or implicitly cancells by leaving the local node) - the activity is finished, the recipient doesn't wait for anything (certainly not for an error) 
+        SetError(KErrNone);
+        BindToComplete();
+        SetIdle();
+        }
+    else
+        {
+        CNodeRetryParallelActivity::Cancel(aContext);
+        }
+    }
+
 void CCommsBinderActivity::BindToComplete()
     {
     __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 23));