| 
					
				 | 
			
			
				@@ -35,17 +35,77 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/slice.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/thd.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/profiling/timers.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace grpc { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+namespace { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void WatchStateChange(void* arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}  // namespace 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Constantly watches channel connectivity status to reconnect a transiently 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// disconnected channel. This is a temporary work-around before we have retry 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// support. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class ChannelConnectivityWatcher { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ChannelConnectivityWatcher(Channel* channel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      : channel_(channel), thd_id_(0), being_destroyed_(0) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void WatchStateChangeImpl() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_connectivity_state state = GRPC_CHANNEL_IDLE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while (state != GRPC_CHANNEL_SHUTDOWN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (gpr_atm_no_barrier_load(&being_destroyed_) == 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      channel_->WaitForStateChange( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          state, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                              gpr_time_from_seconds(1, GPR_TIMESPAN))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      state = channel_->GetState(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void StartWatching() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_thd_options options = gpr_thd_options_default(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_thd_options_set_joinable(&options); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_thd_new(&thd_id_, &WatchStateChange, this, &options); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void Destroy() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (thd_id_ != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_atm_no_barrier_store(&being_destroyed_, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_thd_join(thd_id_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Channel* channel_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_thd_id thd_id_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm being_destroyed_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+namespace { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void WatchStateChange(void* arg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ChannelConnectivityWatcher* watcher = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      static_cast<ChannelConnectivityWatcher*>(arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  watcher->WatchStateChangeImpl(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}  // namespace 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static internal::GrpcLibraryInitializer g_gli_initializer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 Channel::Channel(const grpc::string& host, grpc_channel* channel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    : host_(host), c_channel_(channel) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    : connectivity_watcher_(new ChannelConnectivityWatcher(this)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      host_(host), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      c_channel_(channel) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   g_gli_initializer.summon(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (host != "inproc") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    connectivity_watcher_->StartWatching(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Channel::~Channel() { grpc_channel_destroy(c_channel_); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Channel::~Channel() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  connectivity_watcher_->Destroy(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_channel_destroy(c_channel_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |