| 
					
				 | 
			
			
				@@ -102,6 +102,14 @@ class PickFirst : public LoadBalancingPolicy { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       PickFirst* p = static_cast<PickFirst*>(policy()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       p->Unref(DEBUG_LOCATION, "subchannel_list"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool in_transient_failure() const { return in_transient_failure_; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void set_in_transient_failure(bool in_transient_failure) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      in_transient_failure_ = in_transient_failure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool in_transient_failure_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   class Picker : public SubchannelPicker { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -368,12 +376,21 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       p->selected_ = nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       StopConnectivityWatchLocked(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_error* new_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "selected subchannel not ready; switching to pending update", &error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      p->channel_control_helper()->UpdateState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(new_error), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(new_error))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // Set our state to that of the pending subchannel list. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (p->subchannel_list_->in_transient_failure()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_error* new_error = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "selected subchannel failed; switching to pending update", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                &error, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        p->channel_control_helper()->UpdateState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(new_error), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            UniquePtr<SubchannelPicker>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                New<TransientFailurePicker>(new_error))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        p->channel_control_helper()->UpdateState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            UniquePtr<SubchannelPicker>(New<QueuePicker>(p->Ref()))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // If the selected subchannel goes bad, request a re-resolution. We 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -382,7 +399,6 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // to connect to the re-resolved backends until we leave IDLE state. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         p->idle_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         p->channel_control_helper()->RequestReresolution(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // In transient failure. Rely on re-resolution to recover. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         p->selected_ = nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         StopConnectivityWatchLocked(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         p->channel_control_helper()->UpdateState( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -418,6 +434,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   //    for a subchannel in p->latest_pending_subchannel_list_.  The 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   //    goal here is to find a subchannel from the update that we can 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   //    select in place of the current one. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  subchannel_list()->set_in_transient_failure(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   switch (connectivity_state) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case GRPC_CHANNEL_READY: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // Renew notification. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -431,17 +448,25 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       size_t next_index = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           (sd->Index() + 1) % subchannel_list()->num_subchannels(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       sd = subchannel_list()->subchannel(next_index); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // Case 1: Only set state to TRANSIENT_FAILURE if we've tried 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // all subchannels. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (sd->Index() == 0 && subchannel_list() == p->subchannel_list_.get()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        p->channel_control_helper()->RequestReresolution(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        grpc_error* new_error = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "failed to connect to all addresses", &error, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        p->channel_control_helper()->UpdateState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(new_error), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            UniquePtr<SubchannelPicker>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                New<TransientFailurePicker>(new_error))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // If we're tried all subchannels, set state to TRANSIENT_FAILURE. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (sd->Index() == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Re-resolve if this is the most recent subchannel list. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (subchannel_list() == (p->latest_pending_subchannel_list_ != nullptr 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                      ? p->latest_pending_subchannel_list_.get() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                      : p->subchannel_list_.get())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          p->channel_control_helper()->RequestReresolution(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        subchannel_list()->set_in_transient_failure(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Only report new state in case 1. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (subchannel_list() == p->subchannel_list_.get()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          grpc_error* new_error = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "failed to connect to all addresses", &error, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          p->channel_control_helper()->UpdateState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(new_error), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              UniquePtr<SubchannelPicker>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  New<TransientFailurePicker>(new_error))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       sd->CheckConnectivityStateAndStartWatchingLocked(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 |