[glom/feature_backup2: 6/6] Improve backup saving and add backup restoring.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom/feature_backup2: 6/6] Improve backup saving and add backup restoring.
- Date: Sun, 4 Jul 2010 13:43:34 +0000 (UTC)
commit fe557320ae35d9d0164b505ee5da039dacfd9d36
Author: Murray Cumming <murrayc murrayc com>
Date: Fri Jul 2 17:05:48 2010 +0200
Improve backup saving and add backup restoring.
* glom/libglom/document/document.[h|cc]: Added get/set_is_backup_file(),
saved in the XML document..
on_menu_developer_export_backup(): Mark the .glom file as a backup file.
Rename recreate_database() to recreate_database_from_example().
on_document_load(): Handle backup .glom files similarly to examples files,
but using the backup file instead of example data.
* glom/frame_glom.cc:
* glom/libglom/connection_pool.[h|cc]:
* glom/libglom/connectionpool_backends/backend.[h|cc]: startup(): Return a
StartupErrors enum, to provide more clues, for instance to say that backup
data was found.
Add get/set_database_directory_uri(), replacing the one in sqlite.[h|cc] and
replacing set_self_hosting_data_uri() in postgres_self.[hc|cc].
save_backup(): Don't take a filepath - use get_database_directory_uri()
instead.
Added convert_backup() to restore from a backup.
* glom/libglom/connectionpool_backends/sqlite.[h|cc]:
* glom/libglom/connectionpool_backends/postgres.[h|cc]:
get_path_to_postgres_executable(): Catch exceptions from Glib::build_filename().
save_backup(): Use --format=c with pg_dump, because the default one can't be
used with pg_restore.
Implement convert_backup(), using pg_restore.
Added get_self_hosting_config_path(), get_self_hosting_data_path() and
get_self_hosting_backup_path() to avoid copy/pasting magic paths.
* glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
Adapted.
* glom/application.[h|cc]:
* tests/test_selfhosting_new_empty.cc: Adapted to check the enum result from
startup().
ChangeLog | 34 ++++
glom/application.cc | 86 +++++++--
glom/application.h | 2 +-
glom/frame_glom.cc | 22 ++-
glom/libglom/connectionpool.cc | 50 ++++-
glom/libglom/connectionpool.h | 21 ++-
glom/libglom/connectionpool_backends/backend.cc | 15 ++-
glom/libglom/connectionpool_backends/backend.h | 30 +++-
glom/libglom/connectionpool_backends/postgres.cc | 203 +++++++++++++++++++-
glom/libglom/connectionpool_backends/postgres.h | 29 +++-
.../connectionpool_backends/postgres_self.cc | 116 +++++------
.../connectionpool_backends/postgres_self.h | 12 +-
glom/libglom/connectionpool_backends/sqlite.cc | 19 +-
glom/libglom/connectionpool_backends/sqlite.h | 9 +-
glom/libglom/document/document.cc | 21 ++-
glom/libglom/document/document.h | 4 +
tests/test_selfhosting_new_empty.cc | 2 +-
17 files changed, 536 insertions(+), 139 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index cad2a5d..0139106 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2010-07-03 Murray Cumming <murrayc murrayc com>
+
+ Improve backup saving and add backup restoring.
+
+ * glom/libglom/document/document.[h|cc]: Added get/set_is_backup_file(),
+ saved in the XML document..
+ on_menu_developer_export_backup(): Mark the .glom file as a backup file.
+ Rename recreate_database() to recreate_database_from_example().
+ on_document_load(): Handle backup .glom files similarly to examples files,
+ but using the backup file instead of example data.
+ * glom/frame_glom.cc:
+ * glom/libglom/connection_pool.[h|cc]:
+ * glom/libglom/connectionpool_backends/backend.[h|cc]: startup(): Return a
+ StartupErrors enum, to provide more clues, for instance to say that backup
+ data was found.
+ Add get/set_database_directory_uri(), replacing the one in sqlite.[h|cc] and
+ replacing set_self_hosting_data_uri() in postgres_self.[hc|cc].
+ save_backup(): Don't take a filepath - use get_database_directory_uri()
+ instead.
+ Added convert_backup() to restore from a backup.
+ * glom/libglom/connectionpool_backends/sqlite.[h|cc]:
+ * glom/libglom/connectionpool_backends/postgres.[h|cc]:
+ get_path_to_postgres_executable(): Catch exceptions from Glib::build_filename().
+ save_backup(): Use --format=c with pg_dump, because the default one can't be
+ used with pg_restore.
+ Implement convert_backup(), using pg_restore.
+ Added get_self_hosting_config_path(), get_self_hosting_data_path() and
+ get_self_hosting_backup_path() to avoid copy/pasting magic paths.
+ * glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
+ Adapted.
+ * glom/application.[h|cc]:
+ * tests/test_selfhosting_new_empty.cc: Adapted to check the enum result from
+ startup().
+
2010-07-02 Murray Cumming <murrayc murrayc com>
Document: Avoid a crash when creating the parent directory.
diff --git a/glom/application.cc b/glom/application.cc
index 4150641..e74b723 100644
--- a/glom/application.cc
+++ b/glom/application.cc
@@ -1023,26 +1023,39 @@ bool Application::on_document_load()
pDocument->set_allow_autosave(false);
#endif // !GLOM_ENABLE_CLIENT_ONLY
- // Example files are not supported in client only mode because they
+ // Example files and backup files are not supported in client only mode because they
// would need to be saved, but saving support is disabled.
#ifndef GLOM_ENABLE_CLIENT_ONLY
const bool is_example = pDocument->get_is_example_file();
+ const bool is_backup = pDocument->get_is_backup_file();
#endif // !GLOM_ENABLE_CLIENT_ONLY
- if(pDocument->get_is_example_file())
+ const std::string original_uri = pDocument->get_file_uri();
+
+ if(is_example || is_backup)
{
-#ifndef GLOM_ENABLE_CLIENT_ONLY
+#ifndef GLOM_ENABLE_CLIENT_ONLY
// Remember the URI to the example file to be able to prevent
// adding the URI to the recently used files in document_history_add.
// We want to add the document that is created from the example
// instead of the example itself.
// TODO: This is a weird hack. Find a nicer way. murrayc.
- m_example_uri = pDocument->get_file_uri();
+ m_example_uri = original_uri;
pDocument->set_file_uri(Glib::ustring()); //Prevent it from defaulting to the read-only examples directory when offering saveas.
//m_ui_save_extra_* are used by offer_saveas() if it's not empty:
m_ui_save_extra_showextras = true;
- m_ui_save_extra_title = _("Creating From Example File");
- m_ui_save_extra_message = _("To use this example file you must save an editable copy of the file. A new database will also be created on the server.");
+
+ if(is_example)
+ {
+ m_ui_save_extra_title = _("Creating From Example File");
+ m_ui_save_extra_message = _("To use this example file you must save an editable copy of the file. A new database will also be created on the server.");
+ }
+ else if(is_backup)
+ {
+ m_ui_save_extra_title = _("Creating From Backup File");
+ m_ui_save_extra_message = _("To use this backup file you must save an editable copy of the file. A new database will also be created on the server.");
+ }
+
m_ui_save_extra_newdb_title = "TODO";
m_ui_save_extra_newdb_hosting_mode = Document::HOSTING_MODE_DEFAULT;
@@ -1063,6 +1076,7 @@ bool Application::on_document_load()
pDocument->set_hosting_mode(m_ui_save_extra_newdb_hosting_mode);
m_ui_save_extra_newdb_hosting_mode = Document::HOSTING_MODE_DEFAULT;
pDocument->set_is_example_file(false);
+ pDocument->set_is_backup_file(false);
// For self-hosting, we will choose a port later. For central
// hosting, try several default ports. Don't use the values that
@@ -1128,7 +1142,7 @@ bool Application::on_document_load()
bool test = false;
#ifndef GLOM_ENABLE_CLIENT_ONLY
- if(is_example)
+ if(is_example || is_backup)
{
//The user has already had the chance to specify a new filename and database name.
test = m_pFrame->connection_request_password_and_choose_new_database_name();
@@ -1182,7 +1196,7 @@ bool Application::on_document_load()
//Create the example database:
//connection_request_password_and_choose_new_database_name() has already change the database name to a new unused one:
bool user_cancelled = false;
- const bool test = recreate_database(user_cancelled);
+ const bool test = recreate_database_from_example(user_cancelled);
if(!test)
{
// TODO: Do we need to call connection_pool->cleanup() here, for
@@ -1194,7 +1208,7 @@ bool Application::on_document_load()
//Let the user try again.
//A warning has already been shown.
//TODO: No, I don't think there is a warning.
- std::cerr << "Application::on_document_load(): recreate_database() failed." << std::endl;
+ std::cerr << "Application::on_document_load(): recreate_database_from_example() failed." << std::endl;
return offer_new_or_existing();
}
else
@@ -1210,6 +1224,37 @@ bool Application::on_document_load()
pDocument->set_userlevel(user_level); //Change it back.
}
}
+ else if(is_backup)
+ {
+ std::string original_dir_path;
+
+ Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_uri(original_uri);
+ if(gio_file)
+ {
+ Glib::RefPtr<Gio::File> parent = gio_file->get_parent();
+ if(parent)
+ {
+ try
+ {
+ original_dir_path = Glib::filename_from_uri(parent->get_uri());
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << ": Glib::filename_from_uri() failed: " << ex.what() << std::endl;
+ }
+ }
+ }
+
+ if(original_dir_path.empty())
+ {
+ std::cerr << G_STRFUNC << ": original_dir_path is empty." << std::endl;
+ return false;
+ }
+
+ //Restore the database from the backup:
+ std::cout << "DEBUG: original_dir_path=" << original_dir_path << std::endl;
+ const bool restored = connection_pool->convert_backup(ConnectionPool::SlotProgress() /* TODO */, original_dir_path);
+ }
#endif // !GLOM_ENABLE_CLIENT_ONLY
//Switch to operator mode when opening new documents:
@@ -1587,7 +1632,7 @@ void Application::on_menu_help_contents()
#endif //GLOM_ENABLE_MAEMO
#ifndef GLOM_ENABLE_CLIENT_ONLY
-bool Application::recreate_database(bool& user_cancelled)
+bool Application::recreate_database_from_example(bool& user_cancelled)
{
//Create a database, based on the information in the current document:
Document* pDocument = static_cast<Document*>(get_document());
@@ -1618,7 +1663,7 @@ bool Application::recreate_database(bool& user_cancelled)
if(!error.get())
{
#endif // GLIBMM_EXCEPTIONS_ENABLED
- g_warning("Application::recreate_database(): Failed because database exists already.");
+ g_warning("Application::recreate_database_from_example(): Failed because database exists already.");
return false; //Connection to the database succeeded, because no exception was thrown. so the database exists already.
#ifndef GLIBMM_EXCEPTIONS_ENABLED
@@ -1639,7 +1684,7 @@ bool Application::recreate_database(bool& user_cancelled)
if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_SERVER)
{
user_cancelled = true; //Eventually, the user will cancel after retrying.
- g_warning("Application::recreate_database(): Failed because connection to server failed, without specifying a database.");
+ g_warning("Application::recreate_database_from_example(): Failed because connection to server failed, without specifying a database.");
return false;
}
#ifndef GLIBMM_EXCEPTIONS_ENABLED
@@ -1700,7 +1745,7 @@ bool Application::recreate_database(bool& user_cancelled)
{
const std::exception& ex = *error.get();
#endif // GLIBMM_EXCEPTIONS_ENABLED
- g_warning("Application::recreate_database(): Failed to connect to the newly-created database.");
+ g_warning("Application::recreate_database_from_example(): Failed to connect to the newly-created database.");
return false;
}
@@ -1721,7 +1766,7 @@ bool Application::recreate_database(bool& user_cancelled)
dialog_progress->pulse();
if(!table_creation_succeeded)
{
- g_warning("Application::recreate_database(): CREATE TABLE failed with the newly-created database.");
+ g_warning("Application::recreate_database_from_example(): CREATE TABLE failed with the newly-created database.");
return false;
}
}
@@ -1749,13 +1794,13 @@ bool Application::recreate_database(bool& user_cancelled)
if(!table_insert_succeeded)
{
- g_warning("Application::recreate_database(): INSERT of example data failed with the newly-created database.");
+ g_warning("Application::recreate_database_from_example(): INSERT of example data failed with the newly-created database.");
return false;
}
//}
//catch(const std::exception& ex)
//{
- // std::cerr << "Application::recreate_database(): exception: " << ex.what() << std::endl;
+ // std::cerr << "Application::recreate_database_from_example(): exception: " << ex.what() << std::endl;
//HandleError(ex);
//}
@@ -2171,6 +2216,7 @@ void Application::on_menu_file_save_as_example()
const bool bTest = document->save();
document->set_is_example_file(false);
+ document->set_is_backup_file(false);
document->set_file_uri(file_uriOld);
document->set_allow_autosave(true);
@@ -2509,17 +2555,17 @@ void Application::on_menu_developer_export_backup()
document->set_allow_autosave(false); //Prevent saving while we modify the document:
const Glib::ustring fileuri_old = document->get_file_uri();
document->set_file_uri(Glib::filename_to_uri(filepath_document), true); //true = enforce file extension;
+ document->set_is_backup_file(true);
bool saved = document->save();
+
document->set_file_uri(fileuri_old);
+ document->set_is_backup_file(false);
document->set_allow_autosave(true);
if(saved)
{
- //Save a backup of the data there:
- const std::string& filepath_output = Glib::build_filename(path_dir, "backup");
-
ConnectionPool* connection_pool = ConnectionPool::get_instance();
- saved = connection_pool->save_backup(ConnectionPool::SlotProgress() /* TODO */, filepath_output);
+ saved = connection_pool->save_backup(ConnectionPool::SlotProgress() /* TODO */, path_dir);
}
if(!saved)
diff --git a/glom/application.h b/glom/application.h
index 04c90c0..3b70e49 100644
--- a/glom/application.h
+++ b/glom/application.h
@@ -179,7 +179,7 @@ private:
Document* on_connection_pool_get_document();
- bool recreate_database(bool& user_cancelled); //return indicates success.
+ bool recreate_database_from_example(bool& user_cancelled); //return indicates success.
void stop_self_hosting_of_document_database();
void on_connection_avahi_begin();
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index 1859316..3ea7506 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -1113,7 +1113,13 @@ void Frame_Glom::on_menu_file_toggle_share(const Glib::RefPtr<Gtk::ToggleAction>
}
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::StartupErrors started = connectionpool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) );
+ if(started != ConnectionPool::Backend::STARTUPERROR_NONE)
+ {
+ std::cerr << G_STRFUNC << ": startup() failed." << std::endl;
+ //TODO: Tell the user.
+ }
+
connectionpool->set_ready_to_connect();
if(m_dialog_progess_connection_startup)
@@ -2145,8 +2151,13 @@ bool Frame_Glom::connection_request_password_and_choose_new_database_name()
}
// Do startup, such as starting the self-hosting database server
- if(!connection_pool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) ))
+ const ConnectionPool::StartupErrors started =
+ connection_pool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) );
+ if(started != ConnectionPool::Backend::STARTUPERROR_NONE)
+ {
+ std::cerr << G_STRFUNC << ": startup() failed." << std::endl;
return false;
+ }
if(m_dialog_progess_connection_startup)
{
@@ -2317,8 +2328,13 @@ bool Frame_Glom::connection_request_password_and_attempt(bool& database_not_foun
//Start a self-hosted server if necessary:
ConnectionPool* connection_pool = ConnectionPool::get_instance();
connection_pool->setup_from_document(document);
- if(!connection_pool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) ))
+ const ConnectionPool::StartupErrors started =
+ connection_pool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) );
+ if(started != ConnectionPool::Backend::STARTUPERROR_NONE)
+ {
+ std::cerr << G_STRFUNC << ": startup() failed." << std::endl;
return false;
+ }
if(m_dialog_progess_connection_startup)
{
diff --git a/glom/libglom/connectionpool.cc b/glom/libglom/connectionpool.cc
index 6027de5..f7bb540 100644
--- a/glom/libglom/connectionpool.cc
+++ b/glom/libglom/connectionpool.cc
@@ -136,7 +136,7 @@ void ConnectionPool::setup_from_document(const Document* document)
case Document::HOSTING_MODE_POSTGRES_SELF:
{
ConnectionPoolBackends::PostgresSelfHosted* backend = new ConnectionPoolBackends::PostgresSelfHosted;
- backend->set_self_hosting_data_uri(document->get_connection_self_hosted_directory_uri());
+ backend->set_database_directory_uri(document->get_connection_self_hosted_directory_uri());
set_backend(std::auto_ptr<ConnectionPool::Backend>(backend));
}
break;
@@ -415,10 +415,43 @@ void ConnectionPool::set_user(const Glib::ustring& value)
invalidate_connection();
}
-bool ConnectionPool::save_backup(const SlotProgress& slot_progress, const std::string& filepath_output)
+bool ConnectionPool::save_backup(const SlotProgress& slot_progress, const std::string& path_dir)
+{
+ g_assert(m_backend.get());
+
+ const std::string old_uri = m_backend->get_database_directory_uri();
+
+ std::string uri;
+ try
+ {
+ //TODO: Avoid the copy/paste of glom_postgres_data and make it work for sqlite too.
+ const std::string subdir = Glib::build_filename(path_dir, "glom_postgres_data");
+ uri = Glib::filename_to_uri(subdir);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << ": exception from Glib::build_filename(): " << ex.what() << std::endl;
+ return false;
+ }
+
+ m_backend->set_database_directory_uri(uri);
+ const bool result = m_backend->save_backup(slot_progress, m_user, m_password, m_database);
+ m_backend->set_database_directory_uri(old_uri);
+ return result;
+}
+
+bool ConnectionPool::convert_backup(const SlotProgress& slot_progress, const std::string& path_dir)
{
g_assert(m_backend.get());
- return m_backend->save_backup(slot_progress, filepath_output, m_user, m_password, m_database);
+
+ //TODO: Avoid this copy/paste of the directory name:
+ std::string path_dir_to_use = path_dir;
+ if(!path_dir_to_use.empty())
+ {
+ path_dir_to_use = Glib::build_filename(path_dir, "glom_postgres_data");
+ }
+
+ return m_backend->convert_backup(slot_progress, path_dir_to_use, m_user, m_password);
}
void ConnectionPool::set_password(const Glib::ustring& value)
@@ -574,13 +607,14 @@ static void on_linux_signal(int signum)
}
}
-bool ConnectionPool::startup(const SlotProgress& slot_progress, bool network_shared)
+ConnectionPool::StartupErrors ConnectionPool::startup(const SlotProgress& slot_progress, bool network_shared)
{
if(!m_backend.get())
- return false;
+ return Backend::STARTUPERROR_FAILED_UNKNOWN_REASON;
- if(!m_backend->startup(slot_progress, network_shared))
- return false;
+ const Backend::StartupErrors started = m_backend->startup(slot_progress, network_shared);
+ if(started != Backend::STARTUPERROR_NONE)
+ return started;
#ifndef G_OS_WIN32
//Let clients discover this server via avahi:
@@ -591,7 +625,7 @@ bool ConnectionPool::startup(const SlotProgress& slot_progress, bool network_sha
//Comment this out if you want to see the backtrace in a debugger.
//previous_sig_handler = signal(SIGSEGV, &on_linux_signal);
- return true;
+ return started;
}
bool ConnectionPool::cleanup(const SlotProgress& slot_progress)
diff --git a/glom/libglom/connectionpool.h b/glom/libglom/connectionpool.h
index 18c59e9..67737a3 100644
--- a/glom/libglom/connectionpool.h
+++ b/glom/libglom/connectionpool.h
@@ -163,7 +163,20 @@ public:
void create_database(const Glib::ustring& database_name, std::auto_ptr<Glib::Error>& error);
#endif
- bool save_backup(const SlotProgress& slot_progress, const std::string& filepath_output);
+ /** Save a backup of the database in a tarball.
+ * This backup can later be used to recreate the database,
+ * for instance with a later version of PostgreSQL.
+ * See @convert_backup().
+ * @param path_dir The top-level directory for the backup file, using the normal directory structure.
+ *
+ */
+ bool save_backup(const SlotProgress& slot_progress, const std::string& path_dir);
+
+ /** Use a backup of the database in a tarball to create a new database.
+ * @param path_dir The top-level directory for the backup file, using the normal directory structure.
+ * See save_backup().
+ */
+ bool convert_backup(const SlotProgress& slot_progress, const std::string& path_dir);
void set_user(const Glib::ustring& value);
void set_password(const Glib::ustring& value);
@@ -189,7 +202,9 @@ public:
*/
InitErrors initialize(const SlotProgress& slot_progress, bool network_shared = false);
- /** Start a database server instance for the exisiting database files.
+ typedef Backend::StartupErrors StartupErrors;
+
+ /** Start a database server instance for the existing 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,
@@ -197,7 +212,7 @@ public:
* @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 network_shared = false);
+ StartupErrors startup(const SlotProgress& slot_progress, bool network_shared = false);
/** Stop the database server instance for the database files.
*
diff --git a/glom/libglom/connectionpool_backends/backend.cc b/glom/libglom/connectionpool_backends/backend.cc
index 201786c..c65449f 100644
--- a/glom/libglom/connectionpool_backends/backend.cc
+++ b/glom/libglom/connectionpool_backends/backend.cc
@@ -50,9 +50,9 @@ Backend::InitErrors Backend::initialize(const SlotProgress& /* slot_progress */,
return INITERROR_NONE;
}
-bool Backend::startup(const SlotProgress& /* slot_progress */, bool /* network_shared */)
+Backend::StartupErrors Backend::startup(const SlotProgress& /* slot_progress */, bool /* network_shared */)
{
- return true;
+ return STARTUPERROR_NONE;
}
bool Backend::cleanup(const SlotProgress& /* slot_progress */)
@@ -296,6 +296,17 @@ bool Backend::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connect
return true;
}
+void Backend::set_database_directory_uri(const std::string& directory_uri)
+{
+ m_database_directory_uri = directory_uri;
+}
+
+std::string Backend::get_database_directory_uri() const
+{
+ return m_database_directory_uri;
+}
+
+
} // namespace ConnectionPoolBackends
} // namespace Glom
diff --git a/glom/libglom/connectionpool_backends/backend.h b/glom/libglom/connectionpool_backends/backend.h
index ad71fc5..2a51d84 100644
--- a/glom/libglom/connectionpool_backends/backend.h
+++ b/glom/libglom/connectionpool_backends/backend.h
@@ -77,6 +77,14 @@ public:
INITERROR_OTHER
};
+ enum StartupErrors
+ {
+ STARTUPERROR_NONE, /*< The database is ready for use. */
+ STARTUPERROR_FAILED_NO_DATA, /*< There is no data for the database. */
+ STARTUPERROR_FAILED_NO_DATA_HAS_BACKUP_DATA, /*< There is no data for the database, but there is a backup file instead. */
+ STARTUPERROR_FAILED_UNKNOWN_REASON /*< Something else failed. */
+ };
+
protected:
/** Helper functions for backend implementations to use, so that these don't
* need to worry whether glibmm was compiled with exceptions or not.
@@ -116,6 +124,14 @@ protected:
*/
virtual const char* get_public_schema_name() const = 0;
+ /** This specifies that Glom should start its own database server instance (if it's PostgreSQL)
+ * for this database, using the database files stored at the specified uri,
+ * or just use that file (if it's sqlite).
+ * Or it can be used temporarily when calling save_backup() to provide the top-level directory path.
+ */
+ void set_database_directory_uri(const std::string& directory_uri);
+ std::string get_database_directory_uri() const;
+
/** This callback should show UI to indicate that work is still happening.
* For instance, a pulsing ProgressBar.
*/
@@ -130,7 +146,7 @@ protected:
* if possible.
*/
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.
@@ -139,7 +155,7 @@ protected:
* @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, bool network_shared = false);
+ virtual StartupErrors 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
@@ -185,7 +201,15 @@ protected:
* This backup can later be used to recreate the database,
* for instance with a later version of PostgreSQL.
*/
- virtual bool save_backup(const SlotProgress& slot_progress, const std::string& filepath_output, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name) = 0;
+ virtual bool save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name) = 0;
+
+ /** Use a backup of the database in a tarball to create a new database.
+ * See save_backup().
+ */
+ virtual bool convert_backup(const SlotProgress& slot_progress, const std::string& base_directory_uri, const Glib::ustring& username, const Glib::ustring& password) = 0;
+
+protected:
+ std::string m_database_directory_uri;
};
} // namespace ConnectionPoolBackends
diff --git a/glom/libglom/connectionpool_backends/postgres.cc b/glom/libglom/connectionpool_backends/postgres.cc
index b51413c..5065d0b 100644
--- a/glom/libglom/connectionpool_backends/postgres.cc
+++ b/glom/libglom/connectionpool_backends/postgres.cc
@@ -24,6 +24,7 @@
#include <libglom/connectionpool_backends/postgres.h>
#include <libglom/spawn_with_feedback.h>
#include <libglom/utils.h>
+#include <giomm.h>
#include <glibmm/i18n.h>
// Uncomment to see debug messages
@@ -476,7 +477,18 @@ std::string Postgres::get_path_to_postgres_executable(const std::string& program
// from the other shared data. We can perhaps still change this later by
// building postgres with another prefix than /local/pgsql.
gchar* installation_directory = g_win32_get_package_installation_directory_of_module(0);
- std::string test = Glib::build_filename(installation_directory, Glib::build_filename("bin", real_program));
+ std::string test;
+
+ try
+ {
+ test = Glib::build_filename(installation_directory, Glib::build_filename("bin", real_program));
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << ": exception from Glib::build_filename(): " << ex.what() << std::endl;
+ return std::string();
+ }
+
g_free(installation_directory);
if(Glib::file_test(test, Glib::FILE_TEST_IS_EXECUTABLE))
@@ -486,7 +498,15 @@ std::string Postgres::get_path_to_postgres_executable(const std::string& program
return Glib::find_program_in_path(real_program);
#else // G_OS_WIN32
// POSTGRES_UTILS_PATH is defined in config.h, based on the configure.
- return Glib::build_filename(POSTGRES_UTILS_PATH, program + EXEEXT);
+ try
+ {
+ return Glib::build_filename(POSTGRES_UTILS_PATH, program + EXEEXT);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << ": exception from Glib::build_filename(): " << ex.what() << std::endl;
+ return std::string();
+ }
#endif // !G_OS_WIN32
}
@@ -502,7 +522,7 @@ Glib::ustring Postgres::port_as_string(int port_num)
return result;
}
-bool Postgres::save_backup(const SlotProgress& slot_progress, const std::string& filepath_output, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name)
+bool Postgres::save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name)
{
/* TODO:
if(m_network_shared && !running)
@@ -539,10 +559,15 @@ bool Postgres::save_backup(const SlotProgress& slot_progress, const std::string&
//TODO: Save the password to .pgpass
+ const std::string path_backup = get_self_hosting_backup_path(std::string(), true /* create parent directory if necessary */);
+ if(path_backup.empty())
+ return false;
+
// Make sure to use double quotes for the executable path, because the
// CreateProcess() API used on Windows does not support single quotes.
const std::string command_dump = "\"" + get_path_to_postgres_executable("pg_dump") + "\"" +
- " --create --file=\"" + filepath_output + "\"" +
+ " --format=c " + // The default (plain) format cannot be used with pg_restore.
+ " --create --file=\"" + path_backup + "\"" +
" --host=\"" + m_host + "\"" +
" --port=" + port_as_string(m_port) +
" --username=\"" + username + "\"" +
@@ -562,6 +587,176 @@ bool Postgres::save_backup(const SlotProgress& slot_progress, const std::string&
return result;
}
+bool Postgres::convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password)
+{
+/* TODO:
+ if(m_network_shared && !running)
+ {
+ std::cerr << G_STRFUNC << ": The self-hosted database is not running." << std::endl;
+ return;
+ }
+*/
+
+ if(m_host.empty())
+ {
+ std::cerr << G_STRFUNC << ": m_host is empty." << std::endl;
+ return false;
+ }
+
+ if(m_port == 0)
+ {
+ std::cerr << G_STRFUNC << ": m_port is empty." << std::endl;
+ return false;
+ }
+
+ //TODO: Remember the existing username and password?
+ if(username.empty())
+ {
+ std::cerr << G_STRFUNC << ": username is empty." << std::endl;
+ return false;
+ }
+
+ if(password.empty())
+ {
+ std::cerr << G_STRFUNC << ": password is empty." << std::endl;
+ return false;
+ }
+
+ //TODO: Save the password to .pgpass
+
+ //Make sure the path exists:
+ const std::string path_backup = get_self_hosting_backup_path(base_directory);
+ if(path_backup.empty() || !file_exists_filepath(path_backup))
+ {
+ std::cerr << G_STRFUNC << ": Backup file not found: " << path_backup << std::endl;
+ return false;
+ }
+
+ // Make sure to use double quotes for the executable path, because the
+ // CreateProcess() API used on Windows does not support single quotes.
+ const std::string command_restore = "\"" + get_path_to_postgres_executable("pg_restore") + "\"" +
+ " --create -d template1 " +
+ " --host=\"" + m_host + "\"" +
+ " --port=" + port_as_string(m_port) +
+ " --username=\"" + username + "\"" +
+ " " + path_backup;
+
+ std::cout << "DEBUG: command_restore=" << command_restore << std::endl;
+
+ //TODO: Put the password in .pgpass
+
+ const bool result = Glom::Spawn::execute_command_line_and_wait(command_restore, slot_progress);
+ if(!result)
+ {
+ std::cerr << "Error while attempting to call pg_restore." << std::endl;
+ }
+
+ return result;
+}
+
+std::string Postgres::get_self_hosting_path(bool create, const std::string& child_directory)
+{
+ //Get the filepath of the directory that we should create:
+ const std::string dbdir_uri = m_database_directory_uri;
+ //std::cout << "debug: dbdir_uri=" << dbdir_uri << std::endl;
+
+ std::string dbdir;
+ try
+ {
+ dbdir = Glib::build_filename(
+ Glib::filename_from_uri(dbdir_uri), child_directory);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << ": exception from Glib::build_filename(): " << ex.what() << std::endl;
+ }
+
+ if(file_exists_filepath(dbdir))
+ return dbdir;
+ else if(!create)
+ return std::string();
+
+ //Create the directory:
+
+ //std::cout << "debug: dbdir=" << dbdir << std::endl;
+ g_assert(!dbdir.empty());
+
+ if(create_directory_filepath(dbdir))
+ return dbdir;
+ else
+ return std::string();
+}
+
+std::string Postgres::get_self_hosting_config_path(bool create)
+{
+ return get_self_hosting_path(create, "config");
+}
+
+std::string Postgres::get_self_hosting_data_path(bool create)
+{
+ return get_self_hosting_path(create, "data");
+}
+
+std::string Postgres::get_self_hosting_backup_path(const std::string& base_directory, bool create_parent_dir)
+{
+ //This is a file, not a directory, so we don't use get_self_hosting_path("backup");
+ std::string dbdir;
+ if(base_directory.empty())
+ dbdir = get_self_hosting_path(create_parent_dir);
+ else
+ {
+ dbdir = base_directory;
+ }
+
+ if(dbdir.empty())
+ return std::string();
+
+ try
+ {
+ return Glib::build_filename(dbdir, "backup");
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << ": exception from Glib::build_filename(): " << ex.what() << std::endl;
+ return std::string();
+ }
+}
+
+bool Postgres::create_directory_filepath(const std::string& filepath)
+{
+ if(filepath.empty())
+ return false;
+
+ const int mkdir_succeeded = g_mkdir_with_parents(filepath.c_str(), 0770);
+ if(mkdir_succeeded == -1)
+ {
+ std::cerr << G_STRFUNC << "Error from g_mkdir_with_parents() while trying to create directory: " << filepath << std::endl;
+ perror("Error from g_mkdir_with_parents");
+
+ return false;
+ }
+
+ return true;
+}
+
+bool Postgres::file_exists_filepath(const std::string& filepath)
+{
+ if(filepath.empty())
+ return false;
+
+ const Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(filepath);
+ return file && file->query_exists();
+}
+
+bool Postgres::file_exists_uri(const std::string& uri) const
+{
+ if(uri.empty())
+ return false;
+
+ const Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri);
+ return file && file->query_exists();
+}
+
} //namespace ConnectionPoolBackends
} //namespace Glom
diff --git a/glom/libglom/connectionpool_backends/postgres.h b/glom/libglom/connectionpool_backends/postgres.h
index a887c12..6878f70 100644
--- a/glom/libglom/connectionpool_backends/postgres.h
+++ b/glom/libglom/connectionpool_backends/postgres.h
@@ -52,9 +52,15 @@ public:
*/
static bool check_postgres_gda_client_is_available();
- virtual bool save_backup(const SlotProgress& slot_progress, const std::string& filepath_output, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name);
+ /** Save a backup file, using the same directory layout as used by self-hosting.
+ */
+ virtual bool save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name);
+
+ virtual bool convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password);
static std::string get_path_to_postgres_executable(const std::string& program);
+
+
private:
virtual Field::sql_format get_sql_format() const { return Field::SQL_FORMAT_POSTGRES; }
@@ -63,7 +69,7 @@ private:
virtual const char* get_public_schema_name() const { return "public"; }
virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error);
-
+
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);
@@ -72,7 +78,26 @@ protected:
*/
Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) throw();
+ std::string get_self_hosting_path(bool create = false, const std::string& child_directory = std::string());
+
+ /** Get the path to the config sub-directory, optionally creating it.
+ */
+ std::string get_self_hosting_config_path(bool create = false);
+
+ /** Get the path to the data sub-directory, optionally creating it.
+ */
+ std::string get_self_hosting_data_path(bool create = false);
+
+ /** Get the path to the backup file, regardless of whether it exists.
+ * @param base_directory Where to find the backup file, under a normal Glom directory structure.
+ * If @a base_directory is empty then it uses get_database_directory_uri().
+ */
+ std::string get_self_hosting_backup_path(const std::string& base_directory = std::string(), bool create_parent_dir = false);
+ bool create_directory_filepath(const std::string& filepath);
+ bool file_exists_filepath(const std::string& filepath);
+ bool file_exists_uri(const std::string& uri) const;
+
protected:
static Glib::ustring port_as_string(int port_num);
diff --git a/glom/libglom/connectionpool_backends/postgres_self.cc b/glom/libglom/connectionpool_backends/postgres_self.cc
index 2d67f52..e8c8771 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.cc
+++ b/glom/libglom/connectionpool_backends/postgres_self.cc
@@ -105,7 +105,9 @@ DEFAULT_CONFIG_PG_HBA_REMOTE_EXTRA
#define PORT_POSTGRESQL_SELF_HOSTED_START 5433
#define PORT_POSTGRESQL_SELF_HOSTED_END 5500
-#define DEFAULT_CONFIG_PG_IDENT ""
+static const char* DEFAULT_CONFIG_PG_IDENT = "";
+static const char* FILENAME_DATA = "data";
+static const char* FILENAME_BACKUP = "backup";
PostgresSelfHosted::PostgresSelfHosted()
: m_network_shared(false)
@@ -113,16 +115,6 @@ PostgresSelfHosted::PostgresSelfHosted()
m_host = "localhost";
}
-void PostgresSelfHosted::set_self_hosting_data_uri(const std::string& data_uri)
-{
- if(m_self_hosting_data_uri != data_uri)
- {
- // Can't change data uri if we are running the server on another data uri
- g_assert(!get_self_hosting_active());
- m_self_hosting_data_uri = data_uri;
- }
-}
-
bool PostgresSelfHosted::get_self_hosting_active() const
{
return m_port != 0;
@@ -175,9 +167,9 @@ Backend::InitErrors PostgresSelfHosted::initialize(const SlotProgress& slot_prog
{
m_network_shared = network_shared;
- if(m_self_hosting_data_uri.empty())
+ if(m_database_directory_uri.empty())
{
- std::cerr << "PostgresSelfHosted::initialize: m_self_hosting_data_uri is empty." << std::endl;
+ std::cerr << "PostgresSelfHosted::initialize: m_database_directory_uri is empty." << std::endl;
return INITERROR_OTHER;
}
@@ -188,34 +180,29 @@ Backend::InitErrors PostgresSelfHosted::initialize(const SlotProgress& slot_prog
}
//Get the filepath of the directory that we should create:
- const std::string dbdir_uri = m_self_hosting_data_uri;
+ const std::string dbdir_uri = m_database_directory_uri;
//std::cout << "debug: dbdir_uri=" << dbdir_uri << std::endl;
- if(directory_exists_uri(dbdir_uri))
+ if(file_exists_uri(dbdir_uri))
return INITERROR_DIRECTORY_ALREADY_EXISTS;
const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
//std::cout << "debug: dbdir=" << dbdir << std::endl;
g_assert(!dbdir.empty());
- //0770 means "this user and his group can read and write and "execute" (meaning add sub-files) this non-executable file".
- //The 0 prefix means that this is octal.
- int mkdir_succeeded = g_mkdir_with_parents(dbdir.c_str(), 0770);
- if(mkdir_succeeded == -1)
+ const bool dbdir_created = create_directory_filepath(dbdir);
+ if(!dbdir_created)
{
- std::cerr << "Error from g_mkdir_with_parents() while trying to create directory: " << dbdir << std::endl;
- perror("Error from g_mkdir_with_parents");
+ std::cerr << "Couldn't create directory: " << dbdir << std::endl;
return INITERROR_COULD_NOT_CREATE_DIRECTORY;
}
//Create the config directory:
- const std::string dbdir_config = dbdir + "/config";
- mkdir_succeeded = g_mkdir_with_parents(dbdir_config.c_str(), 0770);
- if(mkdir_succeeded == -1)
+ const std::string dbdir_config = get_self_hosting_config_path(true /* create */);
+ if(dbdir_config.empty())
{
- std::cerr << "Error from g_mkdir_with_parents() while trying to create directory: " << dbdir_config << std::endl;
- perror("Error from g_mkdir_with_parents");
+ std::cerr << "Couldn't create the config directory: " << dbdir << std::endl;
return INITERROR_COULD_NOT_CREATE_DIRECTORY;
}
@@ -224,10 +211,13 @@ Backend::InitErrors PostgresSelfHosted::initialize(const SlotProgress& slot_prog
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";
- mkdir_succeeded = g_mkdir_with_parents(dbdir_data.c_str(), 0770);
- g_assert(mkdir_succeeded != -1);
+ const std::string dbdir_data = get_self_hosting_data_path(true /* create */);
+ if(dbdir_data.empty())
+ {
+ std::cerr << "Couldn't create the data directory: " << dbdir << std::endl;
+ return INITERROR_COULD_NOT_CREATE_DIRECTORY;
+ }
// initdb creates a new postgres database cluster:
@@ -385,7 +375,7 @@ float PostgresSelfHosted::get_postgresql_utils_version_as_number(const SlotProgr
}
-bool PostgresSelfHosted::startup(const SlotProgress& slot_progress, bool network_shared)
+Backend::StartupErrors PostgresSelfHosted::startup(const SlotProgress& slot_progress, bool network_shared)
{
m_network_shared = network_shared;
@@ -394,40 +384,51 @@ bool PostgresSelfHosted::startup(const SlotProgress& slot_progress, bool network
//g_assert(!get_self_hosting_active());
if(get_self_hosting_active())
- return true; //Just do it once.
-
- const std::string dbdir_uri = m_self_hosting_data_uri;
-
- if(!(directory_exists_uri(dbdir_uri)))
{
- //TODO: Use a return enum or exception so we can tell the user about this:
- std::cerr << "ConnectionPool::create_self_hosting(): The data directory could not be found: " << dbdir_uri << std::endl;
- return false;
+ std::cerr << G_STRFUNC << ": Already started." << std::endl;
+ return STARTUPERROR_NONE; //Just do it once.
}
+
+ const std::string dbdir_uri = m_database_directory_uri;
- //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
+ if(!(file_exists_uri(dbdir_uri)))
+ {
+ std::cerr << "ConnectionPool::create_self_hosting(): The directory could not be found: " << dbdir_uri << std::endl;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
+ }
const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
g_assert(!dbdir.empty());
- const std::string dbdir_data = Glib::build_filename(dbdir, "data");
- const std::string dbdir_data_uri = Glib::filename_to_uri(dbdir_data);
- if(!(directory_exists_uri(dbdir_data_uri)))
+ const std::string dbdir_data = Glib::build_filename(dbdir, FILENAME_DATA);
+ const Glib::ustring dbdir_data_uri = Glib::filename_to_uri(dbdir_data);
+ if(!(file_exists_uri(dbdir_data_uri)))
{
- //TODO: Use a return enum or exception so we can tell the user about this:
- std::cerr << "ConnectionPool::create_self_hosting(): The data sub-directory could not be found." << dbdir_data_uri << std::endl;
- return false;
+ const std::string dbdir_backup = Glib::build_filename(dbdir, FILENAME_BACKUP);
+ const Glib::ustring dbdir_backup_uri = Glib::filename_to_uri(dbdir_backup);
+ if(file_exists_uri(dbdir_backup_uri))
+ {
+ std::cerr << G_STRFUNC << ": There is no data, but there is backup data." << std::endl;
+ //Let the caller convert the backup to real data and then try again:
+ return STARTUPERROR_FAILED_NO_DATA_HAS_BACKUP_DATA;
+ }
+ else
+ {
+ std::cerr << "ConnectionPool::create_self_hosting(): The data sub-directory could not be found." << dbdir_data_uri << std::endl;
+ return STARTUPERROR_FAILED_NO_DATA;
+ }
}
+
+ //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 int available_port = discover_first_free_port(PORT_POSTGRESQL_SELF_HOSTED_START, PORT_POSTGRESQL_SELF_HOSTED_END);
//std::cout << "ConnectionPool::create_self_hosting():() : debug: Available port for self-hosting: " << available_port << std::endl;
if(available_port == 0)
{
- //TODO: Use a return enum or exception so we can tell the user about this:
std::cerr << "ConnectionPool::create_self_hosting(): No port was available between " << PORT_POSTGRESQL_SELF_HOSTED_START << " and " << PORT_POSTGRESQL_SELF_HOSTED_END << std::endl;
- return false;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
}
//TODO: Performance:
@@ -464,12 +465,12 @@ bool PostgresSelfHosted::startup(const SlotProgress& slot_progress, bool network
if(!result)
{
std::cerr << "Error while attempting to self-host a database." << std::endl;
- return false;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
}
m_port = available_port; //Remember it for later.
- return true;
+ return STARTUPERROR_NONE;
}
bool PostgresSelfHosted::cleanup(const SlotProgress& slot_progress)
@@ -481,11 +482,11 @@ bool PostgresSelfHosted::cleanup(const SlotProgress& slot_progress)
if(!get_self_hosting_active())
return true; //Don't try to stop it if we have not started it.
- const std::string dbdir_uri = m_self_hosting_data_uri;
+ const std::string dbdir_uri = m_database_directory_uri;
const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
g_assert(!dbdir.empty());
- const std::string dbdir_data = Glib::build_filename(dbdir, "data");
+ const std::string dbdir_data = Glib::build_filename(dbdir, FILENAME_DATA);
// TODO: Detect other instances on the same computer, and use a different port number,
@@ -527,7 +528,7 @@ bool PostgresSelfHosted::set_network_shared(const SlotProgress& slot_progress, b
m_network_shared = network_shared;
- const std::string dbdir_uri = m_self_hosting_data_uri;
+ const std::string dbdir_uri = m_database_directory_uri;
const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
const std::string dbdir_uri_config = dbdir_uri + "/config";
@@ -777,15 +778,6 @@ bool PostgresSelfHosted::create_text_file(const std::string& file_uri, const std
return true; //Success.
}
-bool PostgresSelfHosted::directory_exists_uri(const std::string& uri)
-{
- if(uri.empty())
- return false;
-
- const Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri);
- return file && file->query_exists();
-}
-
} // namespace ConnectionPoolBackends
} // namespcae Glom
diff --git a/glom/libglom/connectionpool_backends/postgres_self.h b/glom/libglom/connectionpool_backends/postgres_self.h
index 6568ce8..0c1b809 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.h
+++ b/glom/libglom/connectionpool_backends/postgres_self.h
@@ -36,11 +36,6 @@ class PostgresSelfHosted : public Postgres
public:
PostgresSelfHosted();
- /** This specifies that Glom should start its own database server instance
- * for this database, using the database files stored at the specified uri.
- */
- void set_self_hosting_data_uri(const std::string& data_uri);
-
/** Return whether the self-hosted server is currently running.
*
* @result True if it is running, and false otherwise.
@@ -62,7 +57,7 @@ public:
private:
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, bool network_shared = false);
+ virtual StartupErrors startup(const SlotProgress& slot_progress, bool network_shared = false);
virtual bool cleanup(const SlotProgress& slot_progress);
virtual bool set_network_shared(const SlotProgress& slot_progress, bool network_shared = true);
@@ -78,9 +73,6 @@ private:
static bool create_text_file(const std::string& file_uri, const std::string& contents);
- //bool directory_exists_filepath(const std::string& filepath);
- bool directory_exists_uri(const std::string& uri);
-
/** Run the command-line with the --version option to discover what version
* of PostgreSQL is installed, so we can use the appropriate configuration
* options when self-hosting.
@@ -89,8 +81,6 @@ private:
float get_postgresql_utils_version_as_number(const SlotProgress& slot_progress);
- std::string m_self_hosting_data_uri;
-
bool m_network_shared;
};
diff --git a/glom/libglom/connectionpool_backends/sqlite.cc b/glom/libglom/connectionpool_backends/sqlite.cc
index 0d95ee5..712b9be 100644
--- a/glom/libglom/connectionpool_backends/sqlite.cc
+++ b/glom/libglom/connectionpool_backends/sqlite.cc
@@ -34,16 +34,6 @@ Sqlite::Sqlite()
{
}
-void Sqlite::set_database_directory_uri(const std::string& directory_uri)
-{
- m_database_directory_uri = directory_uri;
-}
-
-const std::string& Sqlite::get_database_directory_uri() const
-{
- return m_database_directory_uri;
-}
-
Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
{
Glib::RefPtr<Gnome::Gda::Connection> connection;
@@ -397,12 +387,19 @@ bool Sqlite::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
return recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(), fields_changed, error);
}
-bool Sqlite::save_backup(const SlotProgress& slot_progress, const std::string& filepath_output, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name)
+bool Sqlite::save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name)
{
//TODO:
std::cerr << G_STRFUNC << ": Not implemented.";
}
+bool Sqlite::convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password)
+{
+ //TODO:
+ std::cerr << G_STRFUNC << ": Not implemented.";
+}
+
+
} // namespace ConnectionPoolBackends
} // namespace Glom
diff --git a/glom/libglom/connectionpool_backends/sqlite.h b/glom/libglom/connectionpool_backends/sqlite.h
index 2461714..06a86fe 100644
--- a/glom/libglom/connectionpool_backends/sqlite.h
+++ b/glom/libglom/connectionpool_backends/sqlite.h
@@ -37,9 +37,6 @@ class Sqlite : public Backend
public:
Sqlite();
- void set_database_directory_uri(const std::string& directory_uri);
- const std::string& get_database_directory_uri() const;
-
private:
virtual Field::sql_format get_sql_format() const { return Field::SQL_FORMAT_SQLITE; }
virtual bool supports_remote_access() const { return false; }
@@ -65,10 +62,8 @@ private:
*/
virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
- virtual bool save_backup(const SlotProgress& slot_progress, const std::string& filepath_output, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name);
-
-private:
- std::string m_database_directory_uri;
+ virtual bool save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name);
+ virtual bool convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password);
};
} //namespace ConnectionPoolBackends
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index 72b2ee0..05aafe9 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -135,6 +135,7 @@ namespace Glom
#define GLOM_ATTRIBUTE_FORMAT_VERSION "format_version"
#define GLOM_ATTRIBUTE_IS_EXAMPLE "is_example"
+#define GLOM_ATTRIBUTE_IS_BACKUP "is_backup"
#define GLOM_ATTRIBUTE_CONNECTION_DATABASE_TITLE "database_title"
#define GLOM_NODE_STARTUP_SCRIPT "startup_script"
#define GLOM_ATTRIBUTE_TRANSLATION_ORIGINAL_LOCALE "translation_original_locale"
@@ -253,6 +254,7 @@ Document::Document()
m_block_modified_set(false),
m_allow_auto_save(true), //Save all changes immediately, by default.
m_is_example(false),
+ m_is_backup(false),
m_opened_from_browse(false)
{
m_document_format_version = get_latest_known_document_format_version(); //Default to this for new documents.
@@ -2421,8 +2423,9 @@ bool Document::load_after(int& failure_code)
failure_code = LOAD_FAILURE_CODE_FILE_VERSION_TOO_NEW;
return false;
}
-
+
m_is_example = get_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_EXAMPLE);
+ m_is_backup = get_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_BACKUP);
m_database_title = get_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_CONNECTION_DATABASE_TITLE);
m_startup_script = get_child_text_node(nodeRoot, GLOM_NODE_STARTUP_SCRIPT);
@@ -3367,6 +3370,7 @@ bool Document::save_before()
set_node_attribute_value_as_decimal(nodeRoot, GLOM_ATTRIBUTE_FORMAT_VERSION, m_document_format_version);
set_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_EXAMPLE, m_is_example);
+ set_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_BACKUP, m_is_backup);
set_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_CONNECTION_DATABASE_TITLE, m_database_title);
set_child_text_node(nodeRoot, GLOM_NODE_STARTUP_SCRIPT, m_startup_script);
@@ -4026,6 +4030,21 @@ void Document::set_is_example_file(bool value)
}
+bool Document::get_is_backup_file() const
+{
+ return m_is_backup;
+}
+
+void Document::set_is_backup_file(bool value)
+{
+ if(m_is_backup != value)
+ {
+ m_is_backup = value;
+ set_modified();
+ }
+}
+
+
void Document::set_translation_original_locale(const Glib::ustring& locale)
{
m_translation_original_locale = locale;
diff --git a/glom/libglom/document/document.h b/glom/libglom/document/document.h
index f60861a..f941a67 100644
--- a/glom/libglom/document/document.h
+++ b/glom/libglom/document/document.h
@@ -81,6 +81,9 @@ public:
bool get_is_example_file() const;
void set_is_example_file(bool value = true);
+
+ bool get_is_backup_file() const;
+ void set_is_backup_file(bool value = true);
/* Get version of the document format used for this document.
* This can increase when the file has been re-saved.
@@ -618,6 +621,7 @@ private:
bool m_block_modified_set;
bool m_allow_auto_save;
bool m_is_example;
+ bool m_is_backup;
guint m_document_format_version;
bool m_opened_from_browse;
diff --git a/tests/test_selfhosting_new_empty.cc b/tests/test_selfhosting_new_empty.cc
index 562c630..9917504 100644
--- a/tests/test_selfhosting_new_empty.cc
+++ b/tests/test_selfhosting_new_empty.cc
@@ -169,7 +169,7 @@ int main()
//Start self-hosting:
//TODO: Let this happen automatically on first connection?
const bool started = connection_pool->startup( sigc::ptr_fun(&on_startup_progress) );
- g_assert(started);
+ g_assert(started == ConnectionPool::Backend::STARTUPERROR_NONE);
const bool stopped = connection_pool->cleanup( sigc::ptr_fun(&on_cleanup_progress) );
g_assert(stopped);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]