[glom] Self-Hosting: Retry the connection just-long-enough.



commit 5fc30e204af042783b70f0e7ba8ddd56cafa9797
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Sep 24 16:14:43 2009 +0200

    Self-Hosting: Retry the connection just-long-enough.
    
    * glom/libglom/connectionpool_backends/postgres.[h|cc]: attempt_connect():
    Add a throw() declaration because we know that this really never throws,
    though other similar methods do.
    * glom/libglom/connectionpool_backends/postgres_self.cc: connect():
    If not network-shared then retry every second when the connection fails,
    because the (default) password really must be correct. Seems to work,
    requiring 6 retries on my system.
    However, we must still wait a hard-coded time to be sure of failure
    if the password is not the default one, for instance when network sharing.
    * glom/libglom/spawn_with_feedback.cc:
    execute_command_line_and_wait_until_second_command_returns_success():
    Remove the hacked 8-second wait here.

 ChangeLog                                          |   17 ++++++
 glom/libglom/connectionpool_backends/postgres.cc   |   14 +----
 glom/libglom/connectionpool_backends/postgres.h    |    6 ++-
 .../connectionpool_backends/postgres_self.cc       |   53 +++++++++++++++++++-
 glom/libglom/spawn_with_feedback.cc                |    9 +++-
 glom/utility_widgets/db_adddel/db_adddel.cc        |    2 +-
 6 files changed, 85 insertions(+), 16 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e296180..8ebd957 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2009-09-24  Murray Cumming  <murrayc murrayc com>
+
+	Self-Hosting: Retry the connection just-long-enough.
+
+	* glom/libglom/connectionpool_backends/postgres.[h|cc]: attempt_connect(): 
+	Add a throw() declaration because we know that this really never throws, 
+	though other similar methods do.
+	* glom/libglom/connectionpool_backends/postgres_self.cc: connect():
+	If not network-shared then retry every second when the connection fails, 
+	because the (default) password really must be correct. Seems to work, 
+	requiring 6 retries on my system. 
+	However, we must still wait a hard-coded time to be sure of failure 
+	if the password is not the default one, for instance when network sharing.
+	* glom/libglom/spawn_with_feedback.cc: 
+	execute_command_line_and_wait_until_second_command_returns_success():
+	Remove the hacked 8-second wait here. 
+
 2009-09-23  Murray Cumming  <murrayc murrayc com>
 
 	Renamed Dialog_Glom to Window_BoxHolder.
diff --git a/glom/libglom/connectionpool_backends/postgres.cc b/glom/libglom/connectionpool_backends/postgres.cc
index cce44b3..28dd965 100644
--- a/glom/libglom/connectionpool_backends/postgres.cc
+++ b/glom/libglom/connectionpool_backends/postgres.cc
@@ -57,7 +57,7 @@ float Postgres::get_postgres_server_version() const
   return m_postgres_server_version;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
+Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) throw()
 {
   //We must specify _some_ database even when we just want to create a database.
   //This _might_ be different on some systems. I hope not. murrayc
@@ -66,25 +66,17 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
   const Glib::ustring cnc_string_main = "HOST=" + host + ";PORT=" + port;
   Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + database;
 
-  //std::cout << "debug: connecting: cnc string: " << cnc_string << std::endl;
-#ifdef GLOM_CONNECTION_DEBUG          
-  std::cout << std::endl << "Glom: trying to connect on port=" << port << std::endl;
-#endif
-
   Glib::RefPtr<Gnome::Gda::Connection> connection;
   Glib::RefPtr<Gnome::Gda::DataModel> data_model;
 
   const Glib::ustring auth_string = create_auth_string(username, password);   
  
-#ifdef GLOM_CONNECTION_DEBUG
+#ifdef GLOM_CONNECTION_DEBUG          
+  std::cout << std::endl << "DEBUG: Glom: trying to connect on port=" << port << std::endl;
   std::cout << "DEBUG: ConnectionPoolBackends::Postgres::attempt_connect(): cnc_string=" << cnc_string << std::endl;
   std::cout << "  DEBUG: auth_string=" << auth_string << std::endl;
 #endif
 
-//TODO: Allow the client-only build to specify a read-only connection, 
-//so we can use Gnome::Gda::CONNECTION_OPTIONS_READ_ONLY?
-//But this must be a runtime thing - it can't be a build-time change, 
-//because libglom has no client-only build. It always offers everything.
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   try
   {
diff --git a/glom/libglom/connectionpool_backends/postgres.h b/glom/libglom/connectionpool_backends/postgres.h
index 763825a..9386a6d 100644
--- a/glom/libglom/connectionpool_backends/postgres.h
+++ b/glom/libglom/connectionpool_backends/postgres.h
@@ -63,8 +63,10 @@ private:
 protected:
   bool attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
 
-protected:
-  Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
+  /** Attempt to connect to the database with the specified criteria.
+   * @param error An error if the correction failed.
+   */ 
+  Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) throw();
 
 private:
   float m_postgres_server_version;
diff --git a/glom/libglom/connectionpool_backends/postgres_self.cc b/glom/libglom/connectionpool_backends/postgres_self.cc
index 5640b1f..f4f866a 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.cc
+++ b/glom/libglom/connectionpool_backends/postgres_self.cc
@@ -427,6 +427,16 @@ bool PostgresSelfHosted::set_network_shared(const SlotProgress& /* slot_progress
   return hba_conf_creation_succeeded;
 }
 
+static bool on_timeout_delay(const Glib::RefPtr<Glib::MainLoop>& mainloop)
+{
+  //Allow our mainloop.run() to return:
+  if(mainloop)
+    mainloop->quit();
+    
+  return false;
+}
+
+
 Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
 {
   if(!get_self_hosting_active())
@@ -435,8 +445,49 @@ Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ust
     return Glib::RefPtr<Gnome::Gda::Connection>();
   }
 
-  return attempt_connect("localhost", port_as_string(m_port), database, username, password, error);
+  std::auto_ptr<ExceptionConnection> ex;
+
+  Glib::RefPtr<Gnome::Gda::Connection> result;
+  bool keep_trying = true;
+  guint count_retries = 0;
+  const guint MAX_RETRIES_KNOWN_PASSWORD = 30; /* seconds */
+  const guint MAX_RETRIES_EVER = 60; /* seconds */
+  while(keep_trying)
+  { 
+    result = attempt_connect("localhost", port_as_string(m_port), database, username, password, ex);
+    if(!result && 
+      ex.get() && (ex->get_failure_type() == ExceptionConnection::FAILURE_NO_SERVER))
+    {
+      //It must be using a default password, so any failure would not be due to a wrong password.
+      //However, pg_ctl sometimes reports success before it is really ready to let us connect, 
+      //so in this case we can just keep trying until it works, with a very long timeout.
+      count_retries++;
+      const guint max_retries = m_network_shared ? MAX_RETRIES_EVER : MAX_RETRIES_KNOWN_PASSWORD;
+      if(count_retries > max_retries)
+      {
+        keep_trying = false;
+        continue;
+      }
+
+      std::cout << "DEBUG: Glom::PostgresSelfHosted::connect(): Waiting and retrying the connection due to suspected too-early success of pg_ctl." << std::endl; 
+
+      //Wait:
+      Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
+        sigc::connection connection_timeout = Glib::signal_timeout().connect(
+        sigc::bind(sigc::ptr_fun(&on_timeout_delay), sigc::ref(mainloop)), 
+        1000 /* 1 second */);
+      mainloop->run();
+      connection_timeout.disconnect();
+      
+      keep_trying = true;
+      continue;
+    }
+    
+    keep_trying = false;
+  }
 
+  error = ex;
+  return result;
 }
 
 bool PostgresSelfHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
diff --git a/glom/libglom/spawn_with_feedback.cc b/glom/libglom/spawn_with_feedback.cc
index 17f849c..168fd9d 100644
--- a/glom/libglom/spawn_with_feedback.cc
+++ b/glom/libglom/spawn_with_feedback.cc
@@ -509,6 +509,7 @@ namespace
 
 } //Anonymous namespace
 
+/*
 static bool on_timeout_delay(const Glib::RefPtr<Glib::MainLoop>& mainloop)
 {
   //Allow our mainloop.run() to return:
@@ -517,6 +518,7 @@ static bool on_timeout_delay(const Glib::RefPtr<Glib::MainLoop>& mainloop)
     
   return false;
 }
+*/
 
 bool execute_command_line_and_wait_until_second_command_returns_success(const std::string& command, const std::string& second_command, const SlotProgress& slot_progress, const std::string& success_text)
 {
@@ -552,6 +554,10 @@ bool execute_command_line_and_wait_until_second_command_returns_success(const st
 
   if(success) //response == Gtk::RESPONSE_OK)
   {
+    /* Don't sleep here. Instead we just keep trying to connect until it succeeds, 
+     * timing out during that if necessary.
+     *
+     *
     //Sleep for a bit more, because I think that pg_ctl sometimes reports success too early.
     Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
     sigc::connection connection_timeout = Glib::signal_timeout().connect(
@@ -560,7 +566,8 @@ bool execute_command_line_and_wait_until_second_command_returns_success(const st
     mainloop->run();
 
     connection_timeout.disconnect();
-    
+    */
+
     return true;
   }
   else
diff --git a/glom/utility_widgets/db_adddel/db_adddel.cc b/glom/utility_widgets/db_adddel/db_adddel.cc
index 77c4105..77ba7b5 100644
--- a/glom/utility_widgets/db_adddel/db_adddel.cc
+++ b/glom/utility_widgets/db_adddel/db_adddel.cc
@@ -1933,7 +1933,7 @@ guint DbAddDel::treeview_append_column(const Glib::ustring& title, Gtk::CellRend
     {
      column_width = Utils::get_suitable_field_width_for_widget(*this, layout_item_field);
      column_width = column_width / 3;
-     std::cout << "DEBUG: column_width=" << column_width << std::endl;
+     //std::cout << "DEBUG: column_width=" << column_width << std::endl;
     }
     else
      column_width = 100;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]