glom r2055 - in trunk: . glom glom/libglom glom/libglom/connectionpool_backends glom/libglom/document



Author: murrayc
Date: Fri Apr 10 11:09:16 2009
New Revision: 2055
URL: http://svn.gnome.org/viewvc/glom?rev=2055&view=rev

Log:
2009-04-10  Murray Cumming  <murrayc murrayc com>

* glom/application.[h|cc] init_menus_file(): Add a File/Share On Network 
toggle menu item. Added update_network_shared_ui() to ensure that it 
is checked when appropriate.
open_browsed_document(), on_document_load(): 
Call update_network_shared_ui().
* glom/frame_glom.[h|cc]: on_menu_file_toggle_share(): Handle the 
new menu item, to change the configration and restart the server.

* glom/libglom/document/document.cc: Added set_network_shared(), 
get_network_shared(). load_after(), save_before(): Save it in the 
document. This is the default that will be used when opening a document.
It defaults to not shared.
* glom/glom_document.dtd: Document the new network_shared XML attribute.

* glom/libglom/connectionpool.[h|cc]: get_and_connect(): Only start avahi 
publishing if we are shared on the network.
set_network_shared(): Added this private function to change the configuration.
initialize(), startup(): Added network_shared parameter.
cleanup(): Call invalidate_connection() to prevent use of a connection 
to a stopped server., 
* glom/libglom/connectionpool_backends/backend.[h|cc]: initialize,
  startup, set_network_shared(): Same change as for ConnectionPool.
* glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
initialize(): set_network_share(): Move config file writing to 
set_network_share() and use different pg_hba.conf contents depending on 
whether we are shared on the network.
startup(): Ensure that the configuration is correct.

Modified:
   trunk/ChangeLog
   trunk/glom/application.cc
   trunk/glom/application.h
   trunk/glom/base_db.cc
   trunk/glom/frame_glom.cc
   trunk/glom/frame_glom.h
   trunk/glom/glom_document.dtd
   trunk/glom/libglom/connectionpool.cc
   trunk/glom/libglom/connectionpool.h
   trunk/glom/libglom/connectionpool_backends/backend.cc
   trunk/glom/libglom/connectionpool_backends/backend.h
   trunk/glom/libglom/connectionpool_backends/postgres.cc
   trunk/glom/libglom/connectionpool_backends/postgres_self.cc
   trunk/glom/libglom/connectionpool_backends/postgres_self.h
   trunk/glom/libglom/document/document.cc
   trunk/glom/libglom/document/document.h
   trunk/glom/libglom/utils.cc

Modified: trunk/glom/application.cc
==============================================================================
--- trunk/glom/application.cc	(original)
+++ trunk/glom/application.cc	Fri Apr 10 11:09:16 2009
@@ -327,6 +327,12 @@
   m_refFileActionGroup->add(action, sigc::mem_fun(*m_pFrame, &Frame_Glom::on_menu_file_import));
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
+  m_toggleaction_network_shared = Gtk::ToggleAction::create("BakeryAction_Menu_File_Share", _("Shared On Network"));
+  m_refFileActionGroup->add(m_toggleaction_network_shared);
+  m_connection_toggleaction_network_shared = 
+    m_toggleaction_network_shared->signal_toggled().connect(
+      sigc::mem_fun(*this, &App_Glom::on_menu_file_toggle_share) );
+
   m_refFileActionGroup->add(Gtk::Action::create("GlomAction_Menu_File_Print", Gtk::Stock::PRINT));
   m_refFileActionGroup->add(Gtk::Action::create("GlomAction_File_Print", _("_Standard")),
                         sigc::mem_fun(*m_pFrame, &Frame_Glom::on_menu_file_print) );
@@ -358,8 +364,10 @@
     "        </menu>"
 #ifndef GLOM_ENABLE_CLIENT_ONLY
     "        <menuitem action='BakeryAction_File_SaveAsExample' />"
+    "        <separator/>"
     "        <menuitem action='BakeryAction_Menu_File_Export' />"
     "        <menuitem action='BakeryAction_Menu_File_Import' />"
+    "        <menuitem action='BakeryAction_Menu_File_Share' />"
 #endif // !GLOM_ENABLE_CLIENT_ONLY
     "        <separator/>"
     "        <menu action='GlomAction_Menu_File_Print'>"
@@ -604,6 +612,14 @@
   fill_menu_tables();
 }
 
+void App_Glom::on_menu_file_toggle_share()
+{
+  if(!m_pFrame)
+    return;
+
+  m_pFrame->on_menu_file_toggle_share(m_toggleaction_network_shared);
+}
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 void App_Glom::on_menu_userlevel_developer()
 {
@@ -767,6 +783,9 @@
     {
       document->set_opened_from_browse();
 
+      document->set_network_shared(true); //It is shared by the computer that we opened this from.
+      update_network_shared_ui();
+
       document->set_userlevel(AppState::USERLEVEL_OPERATOR); //TODO: This should happen automatically.
 #ifndef GLOM_ENABLE_CLIENT_ONLY
       update_userlevel_ui();
@@ -1129,6 +1148,8 @@
     //List the non-hidden tables in the menu:
     fill_menu_tables();
 
+    update_network_shared_ui();
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
     pDocument->set_allow_autosave(true);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
@@ -1174,6 +1195,28 @@
   update_userlevel_ui();
 }
 
+void App_Glom::update_network_shared_ui()
+{
+  Document* document = dynamic_cast<Document*>(get_document());
+  if(!document)
+    return;
+
+  //Show the status in the UI:
+  //(get_network_shared() already enforces constraints).
+  const bool shared = document->get_network_shared();
+  m_connection_toggleaction_network_shared.block(); //Prevent signal handling.
+  m_toggleaction_network_shared->set_active(shared);
+  m_connection_toggleaction_network_shared.unblock();
+ 
+  //Do not allow impossible changes:
+  const Document::HostingMode hosting_mode = document->get_hosting_mode();
+  if( (hosting_mode == Document::HOSTING_MODE_POSTGRES_CENTRAL) //Central hosting means that it must be shared on the network.
+    || (hosting_mode == Document::HOSTING_MODE_SQLITE) ) //sqlite does not allow network sharing.
+  {
+    m_toggleaction_network_shared->set_sensitive(false);
+  }
+}
+
 void App_Glom::update_userlevel_ui()
 {
   AppState::userlevels userlevel = get_userlevel();

Modified: trunk/glom/application.h
==============================================================================
--- trunk/glom/application.h	(original)
+++ trunk/glom/application.h	Fri Apr 10 11:09:16 2009
@@ -59,10 +59,16 @@
   void set_mode_data();
   void set_mode_find();
 
+  /** Show in the UI whether the database is shared on the network.
+   */
+  void update_network_shared_ui();
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   void add_developer_action(const Glib::RefPtr<Gtk::Action>& refAction);
   void remove_developer_action(const Glib::RefPtr<Gtk::Action>& refAction);
 
+  /** Show in the UI whether the document is in developer or operator mode.
+   */
   void update_userlevel_ui();
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
@@ -99,6 +105,7 @@
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   void existing_or_new_new();
 
+  void on_menu_file_toggle_share();
   void on_menu_userlevel_developer();
   void on_menu_userlevel_operator();
   void on_menu_file_save_as_example();
@@ -160,6 +167,9 @@
   Glib::RefPtr<Gtk::ToggleAction> m_action_show_layout_toolbar;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
+  Glib::RefPtr<Gtk::ToggleAction> m_toggleaction_network_shared;
+  sigc::connection m_connection_toggleaction_network_shared;
+
   Gtk::VBox* m_pBoxTop;
   Gtk::VBox* m_pBoxSidebar;
   Frame_Glom* m_pFrame;

Modified: trunk/glom/base_db.cc
==============================================================================
--- trunk/glom/base_db.cc	(original)
+++ trunk/glom/base_db.cc	Fri Apr 10 11:09:16 2009
@@ -236,7 +236,7 @@
   }
   catch(const Gnome::Gda::ServerProviderError& ex)
   {
-    std::cout << "debug: Base_DB::query_execute_select(): ServerProviderError: exception from statement_execute_select(): " << ex.what() << std::endl;
+    std::cout << "debug: Base_DB::query_execute_select(): ServerProviderError: exception from statement_execute_select(): code=" << ex.code() << "message=" << ex.what() << std::endl;
   }
   catch(const Glib::Error& ex)
   {

Modified: trunk/glom/frame_glom.cc
==============================================================================
--- trunk/glom/frame_glom.cc	(original)
+++ trunk/glom/frame_glom.cc	Fri Apr 10 11:09:16 2009
@@ -289,13 +289,6 @@
 
     m_pBox_Mode->add(widget);
     widget.show();
-
-    //Show help text:
-    //Notebook_Glom* pNotebook = dynamic_cast<Notebook_Glom*>(&widget);
-    //if(pNotebook)
-   // {
-   //   pNotebook->show_hint();
-   // }
   }
 }
 
@@ -839,6 +832,99 @@
 }
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
+void Frame_Glom::on_menu_file_toggle_share(const Glib::RefPtr<Gtk::ToggleAction>& action)
+{
+  if(!action)
+  {
+    std::cerr << "rame_Glom::on_menu_file_toggle_share(): action was null." << std::endl;
+  }
+
+
+  bool shared = action->get_active(); //Whether it should be shared.
+  bool change = true;
+
+  //Ask user for confirmation:
+  //TODO: Warn that this will be saved as the default if doing this in developer mode?
+  if(shared)
+  {
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Share On Network")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
+    dialog.set_secondary_text(_("Are you sure that you wish to allow other users on the network to use this database?"));
+    dialog.set_transient_for(*get_app_window());
+    dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+    dialog.add_button(_("_Share"), Gtk::RESPONSE_OK);
+
+    const int response = dialog.run();
+    if(response == Gtk::RESPONSE_OK)
+      shared = true;
+    else
+    {
+      shared = false;
+      change = false;
+    }
+  }
+  else
+  {
+    //TODO: Warn about connected users if possible.
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Stop Sharing On Network")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
+    dialog.set_secondary_text(_("Are you sure that you wish to prevent other users on the network from using this database?"));
+    dialog.set_transient_for(*get_app_window());
+    dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+    dialog.add_button(_("_Share"), Gtk::RESPONSE_OK);
+
+    const int response = dialog.run();
+    if(response == Gtk::RESPONSE_OK)
+      shared = false;
+    else
+    {
+      shared = true;
+      change = false;
+    }
+  }
+
+
+  Document* document = get_document();
+  if(document)
+   document->set_network_shared(shared);
+
+
+  //Stop the self-hosted database server,
+  //change its configuration,
+  //and start it again:
+  if(change)
+  {
+    ConnectionPool* connectionpool = ConnectionPool::get_instance();
+    sharedptr<SharedConnection> sharedconnection = connectionpool->connect();
+    if(sharedconnection)
+    {
+      sharedconnection->close();
+      sharedconnection.clear();
+    }	
+
+    connectionpool->cleanup( sigc::mem_fun(*this, &Frame_Glom::on_connection_cleanup_progress) );
+
+    if(m_dialog_progess_connection_cleanup)
+    {
+      delete m_dialog_progess_connection_cleanup;
+      m_dialog_progess_connection_cleanup = 0;
+    }
+
+    connectionpool->set_network_shared(sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress), shared);
+    connectionpool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) );
+    connectionpool->set_ready_to_connect();
+
+    if(m_dialog_progess_connection_startup)
+    {
+      delete m_dialog_progess_connection_startup;
+      m_dialog_progess_connection_startup = 0;
+    }
+  }
+
+  //Update the UI:
+  App_Glom* pApp = dynamic_cast<App_Glom*>(get_app_window());
+  if(pApp)
+    pApp->update_network_shared_ui();
+}
+
 void Frame_Glom::on_menu_file_print()
 {
  Notebook_Glom* notebook_current = dynamic_cast<Notebook_Glom*>(m_pBox_Mode->get_child());

Modified: trunk/glom/frame_glom.h
==============================================================================
--- trunk/glom/frame_glom.h	(original)
+++ trunk/glom/frame_glom.h	Fri Apr 10 11:09:16 2009
@@ -24,6 +24,7 @@
 #include <libglom/libglom_config.h> // For GLOM_ENABLE_CLIENT_ONLY
 
 #include <gtkmm/frame.h>
+#include <gtkmm/toggleaction.h>
 #include <libglom/document/bakery/view/view_composite.h>
 #include <libglom/document/document.h>
 
@@ -77,8 +78,9 @@
   void on_menu_file_export();
   void on_menu_file_import();
   void on_menu_file_print_edit_layouts();
-
 #endif // !GLOM_ENABLE_CLIENT_ONLY
+
+  void on_menu_file_toggle_share(const Glib::RefPtr<Gtk::ToggleAction>& action);
   void on_menu_file_print();
 
   void on_menu_Mode_Data();

Modified: trunk/glom/glom_document.dtd
==============================================================================
--- trunk/glom/glom_document.dtd	(original)
+++ trunk/glom/glom_document.dtd	Fri Apr 10 11:09:16 2009
@@ -24,8 +24,9 @@
      server: The hostname of the PostgreSQL server.
      user: The PostgreSQL user.
      database: The name of the database to connect to on the PostgreSQL server.
-     self_hosted: Whether a local instance of PostgreSQL should be started, to serve the data that is in a glom_postgres_data directory. Deprecated in favor of host_mode.
+     self_hosted: Whether a local instance of PostgreSQL should be started, to serve the data that is in a glom_postgres_data directory. Deprecated in favor of hosting_mode.
      hosting_mode: Can be "postgres_central" (self hosted via a local instance of PostgreSQL), "postgres_self" (a central PostgreSQL instance is used) or "sqlite" (self-hosted via a SQLite file).   
+     network_shared: true if the database (and document) should be shared over the network for use by other users.
 -->
     <!ELEMENT connection EMPTY >
     <!ATTLIST connection
@@ -33,7 +34,8 @@
         user CDATA #IMPLIED
         database CDATA #REQUIRED
         self_hosted (true|false) "false" 
-        hosting_mode CDATA #IMPLIED>
+        hosting_mode CDATA #IMPLIED
+        network_shared (true|false) "false">
 
 <!-- group(s) and table_privs are the permissions for each table.
       However, these are just initial permissions for examples. The real permissions are 

Modified: trunk/glom/libglom/connectionpool.cc
==============================================================================
--- trunk/glom/libglom/connectionpool.cc	(original)
+++ trunk/glom/libglom/connectionpool.cc	Fri Apr 10 11:09:16 2009
@@ -291,7 +291,10 @@
     return result;
 
   if(!(connection_pool->m_backend.get()))
+  {
+    std::cerr << "ConnectionPool::get_and_connect(): m_backend is null." << std::endl;
     return result; //TODO: Return a FAILURE_NO_BACKEND erro?, though that would be tedious.
+  }
   
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   result = connection_pool->connect();
@@ -393,7 +396,9 @@
         //to avoid duplicates.
         //TODO: Only advertize if it makes sense for the backend,
         //it does not for sqlite
-        avahi_start_publishing(); //Stopped in the signal_finished handler.
+        Document* document = get_document();
+        if(document && document->get_network_shared())
+          avahi_start_publishing(); //Stopped in the signal_finished handler.
 #endif // !G_OS_WIN32
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
@@ -495,6 +500,13 @@
   return m_backend->get_string_find_operator();
 }
 
+void ConnectionPool::invalidate_connection()
+{
+  connection_cached.clear();
+  m_refGdaConnection.reset();
+  m_sharedconnection_refcount = 0;
+}
+
 void ConnectionPool::on_sharedconnection_finished()
 {
   //g_warning("ConnectionPool::on_sharedconnection_finished().");
@@ -593,12 +605,12 @@
   }
 }
 
-bool ConnectionPool::startup(const SlotProgress& slot_progress)
+bool ConnectionPool::startup(const SlotProgress& slot_progress, bool network_shared)
 {
   if(!m_backend.get())
     return false;
 
-  if(!m_backend->startup(slot_progress))
+  if(!m_backend->startup(slot_progress, network_shared))
     return false;
 
 #ifndef G_OS_WIN32
@@ -627,8 +639,8 @@
   if(m_backend.get())
     m_backend->cleanup(slot_progress);
 
-  //Make sure that connect() makes a new connection:
-  connection_cached.clear();
+  //Make sure that connect() tries to make a new connection:
+  invalidate_connection();
 
 
 #ifndef G_OS_WIN32
@@ -641,6 +653,15 @@
   previous_sig_handler = SIG_DFL; /* Arbitrary default */
 }
 
+
+bool ConnectionPool::set_network_shared(const SlotProgress& slot_progress, bool network_shared)
+{
+  if(m_backend.get())
+    return m_backend->set_network_shared(slot_progress, network_shared);
+  else
+    return false;
+}
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
 bool ConnectionPool::add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field)
@@ -770,10 +791,10 @@
 }
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
-ConnectionPool::InitErrors ConnectionPool::initialize(const SlotProgress& slot_progress)
+ConnectionPool::InitErrors ConnectionPool::initialize(const SlotProgress& slot_progress, bool network_shared)
 {
   if(m_backend.get())
-    return m_backend->initialize(slot_progress, get_user(), get_password());
+    return m_backend->initialize(slot_progress, get_user(), get_password(), network_shared);
   else
     return Backend::INITERROR_OTHER;
 }
@@ -952,7 +973,7 @@
   epc_publisher_quit(m_epc_publisher);
 #endif // !G_OS_WIN32
   g_object_unref(m_epc_publisher);
-  m_epc_publisher = NULL;
+  m_epc_publisher = 0;
 }
 #endif // !G_OS_WIN32
 

Modified: trunk/glom/libglom/connectionpool.h
==============================================================================
--- trunk/glom/libglom/connectionpool.h	(original)
+++ trunk/glom/libglom/connectionpool.h	Fri Apr 10 11:09:16 2009
@@ -170,21 +170,43 @@
   
   /** Do one-time initialization, such as  creating required database
    * files on disk for later use by their own  database server instance.
+   *
+   * @param slot_progress A callback to call while the work is still happening.
+   * @param network_shared Whether the database (and document) should be available to other users over the network, 
+   * if possible. 
    * @param parent_window A parent window to use as the transient window when displaying errors.
    */
-  InitErrors initialize(const SlotProgress& slot_progress);
+  InitErrors initialize(const SlotProgress& slot_progress, bool network_shared = false);
 
   /** Start a database server instance for the exisiting database files.
+   *
+   * @param slot_progress A callback to call while the work is still happening.
+   * @param network_shared Whether the database (and document) should be available to other users over the network, 
+   * if possible. 
    * @param parent_window The parent window (transient for) of any dialogs shown during this operation.
    * @result Whether the operation was successful.
    */
-  bool startup(const SlotProgress& slot_progress);
+  bool startup(const SlotProgress& slot_progress, bool network_shared = false);
 
   /** Stop the database server instance for the database files.
+   *
+   * @param slot_progress A callback to call while the work is still happening.
    * @param parent_window The parent window (transient for) of any dialogs shown during this operation.
    */
   void cleanup(const SlotProgress& slot_progress);
 
+  /** Change the database server's configration to allow or prevent access from 
+   * other users on the network.
+   *
+   * For current backends, you may use this only before startup(), 
+   * or after cleanup().
+   *
+   * @param slot_progress A callback to call while the work is still happening.
+   * @param network_shared Whether the database (and document) should be available to other users over the network, 
+   * if possible. 
+   */
+  virtual bool set_network_shared(const SlotProgress& slot_progress, bool network_shared = true);
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   bool add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field);
@@ -233,6 +255,11 @@
 private:
   void on_sharedconnection_finished();
 
+  /** We call this when we know that the current connection will no longer work, 
+   * for instance after we have stopped the server.
+   */
+  void invalidate_connection();
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   /** Examine ports one by one, starting at @a starting_port, in increasing order,
    * and return the first one that is available.

Modified: trunk/glom/libglom/connectionpool_backends/backend.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/backend.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/backend.cc	Fri Apr 10 11:09:16 2009
@@ -45,12 +45,12 @@
 namespace ConnectionPoolBackends
 {
 
-Backend::InitErrors Backend::initialize(const SlotProgress& /* slot_progress */, const Glib::ustring& /* initial_username */, const Glib::ustring& /* password */)
+Backend::InitErrors Backend::initialize(const SlotProgress& /* slot_progress */, const Glib::ustring& /* initial_username */, const Glib::ustring& /* password */, bool /* network_shared */)
 {
   return INITERROR_NONE;
 }
 
-bool Backend::startup(const SlotProgress& /* slot_progress */)
+bool Backend::startup(const SlotProgress& /* slot_progress */, bool /* network_shared */)
 {
   return true;
 }
@@ -59,6 +59,11 @@
 {
 }
 
+bool Backend::set_network_shared(const SlotProgress& slot_progress, bool /* network_shared */)
+{
+  return true; //Success at doing nothing.
+}
+
 bool Backend::set_server_operation_value(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const Glib::ustring& path, const Glib::ustring& value, std::auto_ptr<Glib::Error>& error)
 {
 #ifdef GLIBMM_EXCEPTIONS_ENABLED

Modified: trunk/glom/libglom/connectionpool_backends/backend.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/backend.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/backend.h	Fri Apr 10 11:09:16 2009
@@ -118,26 +118,42 @@
    * storage. There is no need to implement this function if the data is centrally
    * hosted rather than hosted by Glom.
    *
-   * @slot_progress A callback to call while the work is still happening.
+   * @param slot_progress A callback to call while the work is still happening.
+   * @param network_shared Whether the database (and document) should be available to other users over the network, 
+   * if possible. 
    */
-  virtual InitErrors initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password);
+  virtual InitErrors initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password, bool network_shared = false);
 
   /** This method is called before the backend is used otherwise. This can
    * be used to start a self-hosted database server. There is no need to implement
    * this function if there is no need for extra startup code.
    *
-   * @slot_progress A callback to call while the work is still happening.
+   * @param slot_progress A callback to call while the work is still happening.
+   * @param network_shared Whether the database (and document) should be available to other users over the network, 
+   * if possible. 
    */
-  virtual bool startup(const SlotProgress& slot_progress);
+  virtual bool startup(const SlotProgress& slot_progress, bool network_shared = false);
 
   /** This method is called when the backend is no longer used. This can be
    * used to shut down a self-hosted database server. There is no need to
    * implement this function if there is no need for extra cleanup code.
    *
-   * @slot_progress A callback to call while the work is still happening.
+   * @param slot_progress A callback to call while the work is still happening.
    */
   virtual void cleanup(const SlotProgress& slot_progress);
 
+  /** Change the database server's configration to allow or prevent access from 
+   * other users on the network.
+   *
+   * For current backends, you may use this only before startup(), 
+   * or after cleanup().
+   *
+   * @param slot_progress A callback to call while the work is still happening.
+   * @param network_shared Whether the database (and document) should be available to other users over the network, 
+   * if possible. 
+   */
+  virtual bool set_network_shared(const SlotProgress& slot_progress, bool network_shared = true);
+
   /** This method is called to create a connection to the database server.
    * There exists only the variant with an error variable as last parameter
    * so we don't need #ifdefs all over the code. This part of the API is only

Modified: trunk/glom/libglom/connectionpool_backends/postgres.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres.cc	Fri Apr 10 11:09:16 2009
@@ -25,7 +25,7 @@
 #include <glibmm/i18n.h>
 
 // Uncomment to see debug messages
-// #define GLOM_CONNECTION_DEBUG
+//#define GLOM_CONNECTION_DEBUG
 
 namespace
 {
@@ -35,7 +35,7 @@
   return "USERNAME=" + username + ";PASSWORD=" + password;
 }
 
-}
+} //anonymous namespace
 
 namespace Glom
 {
@@ -74,7 +74,7 @@
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   try
   {
-    Glib::ustring auth_string = create_auth_string(username, password);
+    const Glib::ustring auth_string = create_auth_string(username, password);
     connection = Gnome::Gda::Connection::open_from_string("PostgreSQL", cnc_string, auth_string);
     
     connection->statement_execute_non_select("SET DATESTYLE = 'ISO'");
@@ -84,14 +84,14 @@
   {
 #else
   std::auto_ptr<Glib::Error> error;
-  Glib::ustring auth_string = create_auth_string(username, password);
+  const Glib::ustring auth_string = create_auth_string(username, password);
   connection = Gnome::Gda::Connection::open_from_string("PostgreSQL", cnc_string, auth_string, Gnome::Gda::CONNECTION_OPTIONS_NONE, error);
   
   if(!error)
-      connection->statement_execute_non_select("SET DATESTYLE = 'ISO'", error);
+    connection->statement_execute_non_select("SET DATESTYLE = 'ISO'", error);
 
   if(!error)
-      data_model = connection->statement_execute_select("SELECT version()", error);
+    data_model = connection->statement_execute_select("SELECT version()", error);
 
   if(glib_error.get())
   {

Modified: trunk/glom/libglom/connectionpool_backends/postgres_self.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_self.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_self.cc	Fri Apr 10 11:09:16 2009
@@ -74,12 +74,25 @@
 namespace ConnectionPoolBackends
 {
 
-#define DEFAULT_CONFIG_PG_HBA "local   all         postgres                          ident sameuser\n\
+//TODO: Do we need these sameuser lines?
+#define DEFAULT_CONFIG_PG_HBA_LOCAL \
+"local   all         postgres                          ident sameuser\n\
 \n\
 # TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD\n\
 \n\
 # local is for Unix domain socket connections only\n\
+# These are just here to make debugging with psql easier:\n\
 local   all         all                               ident sameuser\n\
+local   all         all                               md5\n\
+local   all         postgres                          ident sameuser\n\
+\n\
+# TCP connections from the same computer, with a password:\n\
+# TODO: IPv6 too.\n\
+host    all         all         127.0.0.1    255.255.255.255    md5\n"
+
+#define DEFAULT_CONFIG_PG_HBA_REMOTE \
+DEFAULT_CONFIG_PG_HBA_LOCAL \
+"\n\
 # IPv4 local connections:\n\
 host    all         all         0.0.0.0/0          md5\n\
 # IPv6 local connections:\n\
@@ -91,8 +104,8 @@
 #define DEFAULT_CONFIG_PG_IDENT ""
 
 PostgresSelfHosted::PostgresSelfHosted()
-:
-  m_port(0)
+: m_port(0),
+   m_network_shared(false)
 {
 }
 
@@ -182,8 +195,10 @@
 #endif // #if 0
 }
 
-Backend::InitErrors PostgresSelfHosted::initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password)
+Backend::InitErrors PostgresSelfHosted::initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password, bool network_shared)
 {
+  m_network_shared = network_shared;
+
   if(m_self_hosting_data_uri.empty())
   {
     std::cerr << "PostgresSelfHosted::initialize: m_self_hosting_data_uri is empty." << std::endl;
@@ -230,13 +245,7 @@
   }
 
   //Create these files: environment  pg_hba.conf  pg_ident.conf  start.conf
-
-  const std::string dbdir_uri_config = dbdir_uri + "/config";
-  const bool hba_conf_creation_succeeded = create_text_file(dbdir_uri_config + "/pg_hba.conf", DEFAULT_CONFIG_PG_HBA);
-  g_assert(hba_conf_creation_succeeded);
-
-  const bool ident_conf_creation_succeeded = create_text_file(dbdir_uri_config + "/pg_ident.conf", DEFAULT_CONFIG_PG_IDENT);
-  g_assert(ident_conf_creation_succeeded);
+  set_network_shared(slot_progress, m_network_shared); //Creates pg_hba.conf and pg_ident.conf
 
   //Check that there is not an existing data directory:
   const std::string dbdir_data = dbdir + "/data";
@@ -271,8 +280,10 @@
   return result ? INITERROR_NONE : INITERROR_COULD_NOT_START_SERVER;
 }
 
-bool PostgresSelfHosted::startup(const SlotProgress& slot_progress)
+bool PostgresSelfHosted::startup(const SlotProgress& slot_progress, bool network_shared)
 {
+   m_network_shared = network_shared;
+
   // Don't risk random crashes, although this really shouldn't be called
   // twice of course.
   //g_assert(!get_self_hosting_active());
@@ -289,6 +300,9 @@
     return false;
   }
 
+  //Attempt to ensure that the config files are correct:
+  set_network_shared(slot_progress, m_network_shared); //Creates pg_hba.conf and pg_ident.conf
+
   const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
   g_assert(!dbdir.empty());
 
@@ -399,11 +413,31 @@
   m_port = 0;
 }
 
+bool PostgresSelfHosted::set_network_shared(const SlotProgress& slot_progress, bool network_shared)
+{
+  m_network_shared = network_shared;
+
+  const std::string dbdir_uri = m_self_hosting_data_uri;
+  const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
+
+  const std::string dbdir_uri_config = dbdir_uri + "/config";
+  const char* default_conf_contents = m_network_shared ? DEFAULT_CONFIG_PG_HBA_REMOTE : DEFAULT_CONFIG_PG_HBA_LOCAL;
+  const bool hba_conf_creation_succeeded = create_text_file(dbdir_uri_config + "/pg_hba.conf", default_conf_contents);
+  g_assert(hba_conf_creation_succeeded);
+  if(!hba_conf_creation_succeeded)
+    return false;
+
+  const bool ident_conf_creation_succeeded = create_text_file(dbdir_uri_config + "/pg_ident.conf", DEFAULT_CONFIG_PG_IDENT);
+  g_assert(ident_conf_creation_succeeded);
+
+  return hba_conf_creation_succeeded;
+}
+
 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())
   {
-    error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_BACKEND));
+    error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_BACKEND)); //TODO: But there is a backend. It's just not ready.
     return Glib::RefPtr<Gnome::Gda::Connection>();
   }
 

Modified: trunk/glom/libglom/connectionpool_backends/postgres_self.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_self.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_self.h	Fri Apr 10 11:09:16 2009
@@ -62,10 +62,11 @@
   static std::string get_path_to_postgres_executable(const std::string& program);
 
 private:
-  virtual InitErrors initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password);
+  virtual InitErrors initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password, bool network_shared = false);
 
-  virtual bool startup(const SlotProgress& slot_progress);
+  virtual bool startup(const SlotProgress& slot_progress, bool network_shared = false);
   virtual void cleanup(const SlotProgress& slot_progress);
+  virtual bool set_network_shared(const SlotProgress& slot_progress, bool network_shared = true);
 
   virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
 
@@ -86,6 +87,7 @@
 
   std::string m_self_hosting_data_uri;
   int m_port;
+  bool m_network_shared;
 };
 
 } // namespace ConnectionPoolBackends

Modified: trunk/glom/libglom/document/document.cc
==============================================================================
--- trunk/glom/libglom/document/document.cc	(original)
+++ trunk/glom/libglom/document/document.cc	Fri Apr 10 11:09:16 2009
@@ -53,6 +53,7 @@
 #define GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL "postgres_central"
 #define GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF "postgres_self"
 #define GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE "sqlite"
+#define GLOM_ATTRIBUTE_CONNECTION_NETWORK_SHARED "network_shared"
 #define GLOM_ATTRIBUTE_CONNECTION_SERVER "server"
 #define GLOM_ATTRIBUTE_CONNECTION_PORT "port"
 #define GLOM_ATTRIBUTE_CONNECTION_TRY_OTHER_PORTS "try_other_ports"
@@ -234,6 +235,7 @@
 Document::Document()
 :
   m_hosting_mode(DEFAULT_HOSTED),
+  m_network_shared(false),
   m_connection_port(0),
   m_connection_try_other_ports(false),
   m_block_cache_update(false),
@@ -277,6 +279,29 @@
   return m_hosting_mode;
 }
 
+void Document:: set_network_shared(bool shared)
+{
+  if(shared != m_network_shared)
+  {
+    m_network_shared = shared;
+    set_modified();
+  }
+}
+
+bool Document::get_network_shared() const
+{
+  bool shared = m_network_shared;
+
+  //Enforce constraints:
+  const HostingMode hosting_mode = get_hosting_mode();
+  if(hosting_mode == HOSTING_MODE_POSTGRES_CENTRAL)
+    shared = true; //Central hosting means that it must be shared on the network.
+  else if(hosting_mode == HOSTING_MODE_SQLITE)
+    shared = false; //sqlite does not allow network sharing.
+
+  return m_network_shared;
+}
+
 std::string Document::get_connection_self_hosted_directory_uri() const
 {
   const std::string uri_file = get_file_uri();
@@ -2331,6 +2356,8 @@
       if(nodeConnection)
       {
         //Connection information:
+        m_network_shared = get_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_NETWORK_SHARED, false /* default */);
+
         m_connection_server = get_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SERVER);
         m_connection_port = get_node_attribute_value_as_decimal(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_PORT);
         m_connection_try_other_ports = get_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_TRY_OTHER_PORTS, true /* default */);
@@ -3233,6 +3260,8 @@
       break;
     }
 
+    set_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_NETWORK_SHARED, m_network_shared);
+
     set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SERVER, m_connection_server);
     set_node_attribute_value_as_decimal(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_PORT, m_connection_port);
     set_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_TRY_OTHER_PORTS, m_connection_try_other_ports, true /* default */);

Modified: trunk/glom/libglom/document/document.h
==============================================================================
--- trunk/glom/libglom/document/document.h	(original)
+++ trunk/glom/libglom/document/document.h	Fri Apr 10 11:09:16 2009
@@ -121,16 +121,28 @@
    */
   void set_hosting_mode(HostingMode mode);
 
+  /** This returns how the database is hosted.
+   */
+  HostingMode get_hosting_mode() const;
+
+  /** Whether the database (and document) is shared over the network.
+   * This setting is saved in the file, allowing the database to be 
+   * shared immediately after opening the document.
+   * @param shared true if the database should be shared.
+   */
+  void set_network_shared(bool shared = true);
+
+  /** See set_network_shared().
+   * @result true if the database is (or should be) shared over the network.
+   */
+  bool get_network_shared() const;
+
   void set_connection_server(const Glib::ustring& strVal);
   void set_connection_user(const Glib::ustring& strVal);
   void set_connection_database(const Glib::ustring& strVal);
   void set_connection_port(int port_number);
   void set_connection_try_other_ports(bool val);
 
-  /** This returns how the database is hosted.
-   */
-  HostingMode get_hosting_mode() const;
-
   /** If the database should be hosted, this provides the 
     * path to the directory that contains all the files needed to do that.
     * This is usually a specifically-named directory at the same level as the .glom file. 
@@ -478,6 +490,7 @@
   type_signal_userlevel_changed m_signal_userlevel_changed;
 
   HostingMode m_hosting_mode;
+  bool m_network_shared;
 
   Glib::ustring m_connection_server, m_connection_user, m_connection_database;
   int m_connection_port; //0 means any port. Ignored when self-hosting (which may use a different port each time).

Modified: trunk/glom/libglom/utils.cc
==============================================================================
--- trunk/glom/libglom/utils.cc	(original)
+++ trunk/glom/libglom/utils.cc	Fri Apr 10 11:09:16 2009
@@ -422,9 +422,13 @@
 #else
   std::auto_ptr<ExceptionConnection> conn_error;
   sharedptr<SharedConnection> connection = ConnectionPool::get_instance()->connect(conn_error);
-  if(conn_error.get() != NULL) return list_values;
+  if(conn_error.get())
+    return list_values;
 #endif
 
+  if(!connection)
+    return list_values;
+
   //std::cout << "get_choice_values: Executing SQL: " << sql_query << std::endl;
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   Glib::RefPtr<Gnome::Gda::DataModel> datamodel = connection->get_gda_connection()->statement_execute_select(sql_query);



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