2020#include  " cluster.hpp" 
2121#include  " config.hpp" 
2222#include  " constants.hpp" 
23+ #include  " error_response.hpp" 
2324#include  " execute_request.hpp" 
2425#include  " logger.hpp" 
2526#include  " prepare_request.hpp" 
27+ #include  " query_request.hpp" 
2628#include  " scoped_lock.hpp" 
2729#include  " statement.hpp" 
2830#include  " timer.hpp" 
@@ -158,13 +160,15 @@ Session::Session()
158160  uv_mutex_init (&state_mutex_);
159161  uv_mutex_init (&hosts_mutex_);
160162  uv_mutex_init (&keyspace_mutex_);
163+   uv_mutex_init (&refresh_metadata_future_mutex_);
161164}
162165
163166Session::~Session () {
164167  join ();
165168  uv_mutex_destroy (&state_mutex_);
166169  uv_mutex_destroy (&hosts_mutex_);
167170  uv_mutex_destroy (&keyspace_mutex_);
171+   uv_mutex_destroy (&refresh_metadata_future_mutex_);
168172}
169173
170174void  Session::clear (const  Config& config) {
@@ -173,6 +177,10 @@ void Session::clear(const Config& config) {
173177  metrics_.reset (new  Metrics (config_.thread_count_io () + 1 ));
174178  connect_future_.reset ();
175179  close_future_.reset ();
180+   {
181+     ScopedMutex lock_future (&refresh_metadata_future_mutex_);
182+     refresh_metadata_future_.reset ();
183+   }
176184  { //  Lock hosts
177185    ScopedMutex l (&hosts_mutex_);
178186    hosts_.clear ();
@@ -416,6 +424,76 @@ void Session::notify_connected() {
416424    connect_future_->set ();
417425    connect_future_.reset ();
418426  }
427+   {
428+     ScopedMutex lock_future (&refresh_metadata_future_mutex_);
429+     if  (refresh_metadata_future_) {
430+       refresh_metadata_future_->set ();
431+       refresh_metadata_future_.reset ();
432+     }
433+   }
434+ 
435+   if  (config ().partition_aware_routing ()) {
436+     refresh_metadata_task_ = PeriodicTask::start (loop (),
437+                                                  config ().partition_refresh_frequency_secs ()*1000 ,
438+                                                  this ,
439+                                                  Session::on_refresh_metadata,
440+                                                  Session::on_after_refresh_metadata);
441+   }
442+ }
443+ 
444+ void  Session::on_refresh_metadata (PeriodicTask* task) {
445+   Session* const  session = static_cast <Session*>(task->data ());
446+   {
447+     ScopedMutex l (&session->state_mutex_ );
448+     if  (session->state_ .load (MEMORY_ORDER_RELAXED) != SESSION_STATE_CONNECTED) {
449+       return ; //  The session is finished.
450+     }
451+   }
452+ 
453+   ScopedMutex lock_future (&session->refresh_metadata_future_mutex_ );
454+   if  (!session->refresh_metadata_future_ ) {
455+     session->refresh_metadata_future_ .reset (new  ResponseFuture ());
456+     session->refresh_metadata_future_ ->set_callback (&Session::refresh_metadata_callback, session);
457+ 
458+     cass::QueryRequest* const  query_request =
459+         new  cass::QueryRequest (ControlConnection::get_yb_select_partitions_statement (), 0 );
460+     RequestHandler::Ptr request_handler (new  RequestHandler (
461+         QueryRequest::ConstPtr (query_request), session->refresh_metadata_future_ , session));
462+     session->execute (request_handler);
463+   }
464+ }
465+ 
466+ void  Session::on_after_refresh_metadata (PeriodicTask* task) {
467+   //  No-op.
468+ }
469+ 
470+ void  Session::refresh_metadata_callback (CassFuture* future, void * data) {
471+   ResponseFuture::Ptr rf (static_cast <cass::ResponseFuture*>(future->from ()));
472+   Session* const  session = static_cast <Session*>(data);
473+ 
474+   ScopedMutex lock_future (&session->refresh_metadata_future_mutex_ );
475+   session->refresh_metadata_future_ .reset ();
476+ 
477+   {
478+     ScopedMutex l (&session->state_mutex_ );
479+     if  (session->state_ .load (MEMORY_ORDER_RELAXED) != SESSION_STATE_CONNECTED) {
480+       return ; //  The session is finished.
481+     }
482+   }
483+ 
484+   if  (!rf->ready ()) {
485+     return ; //  ResponseFuture is not ready.
486+   }
487+ 
488+   cass::Response::Ptr response (rf->response ());
489+   if  (!response || check_error_or_invalid_response (" Session" get ())) {
490+     return ; //  Error or null response.
491+   }
492+ 
493+   const  int  protocol_version = session->control_connection_ .protocol_version ();
494+   const  VersionNumber& cassandra_version = session->control_connection_ .cassandra_version ();
495+   ResultResponse* const  partitions_result = static_cast <ResultResponse*>(response.get ());
496+   session->metadata ().update_partitions (protocol_version, cassandra_version, partitions_result);
419497}
420498
421499void  Session::notify_connect_error (CassError code, const  std::string& message) {
@@ -445,12 +523,23 @@ void Session::notify_closed() {
445523    close_future_->set ();
446524    close_future_.reset ();
447525  }
526+ 
527+   ScopedMutex lock_future (&refresh_metadata_future_mutex_);
528+   if  (refresh_metadata_future_) {
529+     refresh_metadata_future_->set ();
530+     refresh_metadata_future_.reset ();
531+   }
448532}
449533
450534void  Session::close_handles () {
451535  EventThread<SessionEvent>::close_handles ();
452536  request_queue_->close_handles ();
453537  config_.load_balancing_policy ()->close_handles ();
538+ 
539+   if  (refresh_metadata_task_) {
540+     PeriodicTask::stop (refresh_metadata_task_);
541+     refresh_metadata_task_.reset ();
542+   }
454543}
455544
456545void  Session::on_run () {
0 commit comments