From 8ff5af4c19838825c9bff2c5856e05cba53b910e Mon Sep 17 00:00:00 2001 From: John Ralls Date: Sun, 17 Jun 2018 16:43:33 -0700 Subject: [PATCH] Decouple QofBook creation from QofSession. So that we don't create two books when loading a session. Step 1 to not having a dirty book when we think we should have no book at all. --- bindings/engine.i | 3 +- bindings/guile/test/test-create-account.scm | 3 +- bindings/python/gnucash_core.i | 3 +- bindings/python/gnucash_core.py | 2 +- bindings/python/sqlite3test.c | 5 +- gnucash/gnome-utils/assistant-xml-encoding.c | 2 +- gnucash/gnome-utils/gnc-file.c | 8 +- gnucash/import-export/aqb/test/test-kvp.c | 4 +- .../dbi/test/test-backend-dbi-basic.cpp | 41 +++---- .../backend/xml/test/test-load-xml2.cpp | 9 +- .../backend/xml/test/test-save-in-lang.cpp | 5 +- .../backend/xml/test/test-xml-account.cpp | 5 +- .../backend/xml/test/test-xml-pricedb.cpp | 8 +- libgnucash/engine/gnc-session.c | 3 +- libgnucash/engine/qofsession.cpp | 111 +++++++++++------- libgnucash/engine/qofsession.h | 2 +- libgnucash/engine/qofsession.hpp | 7 +- .../engine/test-core/test-engine-stuff.cpp | 8 +- .../engine/test/test-qofsession-old.cpp | 21 ++-- libgnucash/engine/test/test-qofsession.cpp | 28 ++--- .../engine/test/test-split-vs-account.cpp | 13 +- 21 files changed, 146 insertions(+), 145 deletions(-) diff --git a/bindings/engine.i b/bindings/engine.i index c6af91a1ec..5ff358ac79 100644 --- a/bindings/engine.i +++ b/bindings/engine.i @@ -181,7 +181,7 @@ functions. */ %include %include -QofSession * qof_session_new (void); +QofSession * qof_session_new (QofBook* book); QofBook * qof_session_get_book (QofSession *session); // TODO: Unroll/remove const char *qof_session_get_url (QofSession *session); @@ -271,6 +271,7 @@ Account * gnc_book_get_template_root(QofBook *book); %typemap(out) KvpValue * " $result = gnc_kvp_value_ptr_to_scm($1); " %typemap(in) GSList *key_path " $1 = gnc_scm_to_gslist_string($input);" +QofBook* qof_book_new (void); void qof_book_options_delete (QofBook *book, GSList *key_path); void qof_book_set_option (QofBook *book, KvpValue *new_value, GSList *key_path); KvpValue* qof_book_get_option (QofBook *book, GSList *key_path); diff --git a/bindings/guile/test/test-create-account.scm b/bindings/guile/test/test-create-account.scm index b972289818..4e3fcc0665 100644 --- a/bindings/guile/test/test-create-account.scm +++ b/bindings/guile/test/test-create-account.scm @@ -25,8 +25,7 @@ (define (run-test) (setenv "GNC_UNINSTALLED" "1") - (let* ((session (qof-session-new)) - (book (qof-session-get-book session)) + (let* ((book (qof-book-new)) (root (xaccMallocAccount book)) (acct (xaccMallocAccount book))) (xaccAccountBeginEdit acct) diff --git a/bindings/python/gnucash_core.i b/bindings/python/gnucash_core.i index bbaf15d1f5..393efa5a65 100644 --- a/bindings/python/gnucash_core.i +++ b/bindings/python/gnucash_core.i @@ -224,4 +224,5 @@ char * no_args[1] = { NULL }; gnc_engine_init(0, no_args); gnc_prefs_init(); %} - +//We must explicitly declare this or it gets left out and we can't create books. +QofBook* qof_book_new (void); diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py index c68ecd737e..6302fba46d 100644 --- a/bindings/python/gnucash_core.py +++ b/bindings/python/gnucash_core.py @@ -103,7 +103,7 @@ class Session(GnuCashCoreClass): you don't need to cleanup and call end() and destroy(), that is handled for you, and the exception is raised. """ - GnuCashCoreClass.__init__(self, instance=instance) + GnuCashCoreClass.__init__(self, Book()) if book_uri is not None: try: self.begin(book_uri, ignore_lock, is_new, force_new) diff --git a/bindings/python/sqlite3test.c b/bindings/python/sqlite3test.c index 40b2720fe9..29bce37e10 100644 --- a/bindings/python/sqlite3test.c +++ b/bindings/python/sqlite3test.c @@ -24,12 +24,15 @@ int main() { const char* testurl = "sqlite3://" TESTFILE; + char * no_args[1] = { NULL }; + QofSession* s = NULL; + qof_log_init(); qof_init(); char * no_args[1] = { NULL }; gnc_engine_init(0, no_args); - QofSession * s = qof_session_new(); + s = qof_session_new(NULL); qof_session_begin(s, testurl, 0, 1, 0); qof_session_load(s, NULL); qof_session_save(s, NULL); diff --git a/gnucash/gnome-utils/assistant-xml-encoding.c b/gnucash/gnome-utils/assistant-xml-encoding.c index 83b93b072a..d702226708 100644 --- a/gnucash/gnome-utils/assistant-xml-encoding.c +++ b/gnucash/gnome-utils/assistant-xml-encoding.c @@ -1080,7 +1080,7 @@ gxi_parse_file (GncXmlImportData *data) /* create a temporary QofSession */ gxi_session_destroy (data); - session = qof_session_new (); + session = qof_session_new (NULL); data->session = session; qof_session_begin (session, data->filename, TRUE, FALSE, FALSE); io_err = qof_session_get_error (session); diff --git a/gnucash/gnome-utils/gnc-file.c b/gnucash/gnome-utils/gnc-file.c index 555cf2d2fb..1b8f70145c 100644 --- a/gnucash/gnome-utils/gnc-file.c +++ b/gnucash/gnome-utils/gnc-file.c @@ -735,7 +735,7 @@ RESTART: /* load the accounts from the users datafile */ /* but first, check to make sure we've got a session going. */ - new_session = qof_session_new (); + new_session = qof_session_new (NULL); // Begin the new session. If we are in read-only mode, ignore the locks. qof_session_begin (new_session, newfile, is_readonly, FALSE, FALSE); @@ -752,6 +752,8 @@ RESTART: filename = gnc_file_dialog (parent, NULL, NULL, directory, GNC_FILE_DIALOG_OPEN); + /* Suppress trying to save the empty session. */ + qof_book_mark_session_saved (qof_session_get_book (new_session)); qof_session_destroy (new_session); new_session = NULL; g_free (directory); @@ -1231,7 +1233,7 @@ gnc_file_do_export(GtkWindow *parent, const char * filename) /* -- this session code is NOT identical in FileOpen and FileSaveAs -- */ - new_session = qof_session_new (); + new_session = qof_session_new (NULL); qof_session_begin (new_session, newfile, FALSE, TRUE, FALSE); io_err = qof_session_get_error (new_session); @@ -1468,7 +1470,7 @@ gnc_file_do_save_as (GtkWindow *parent, const char* filename) save_in_progress++; - new_session = qof_session_new (); + new_session = qof_session_new (NULL); qof_session_begin (new_session, newfile, FALSE, TRUE, FALSE); io_err = qof_session_get_error (new_session); diff --git a/gnucash/import-export/aqb/test/test-kvp.c b/gnucash/import-export/aqb/test/test-kvp.c index 29e7f85455..4e13cebd89 100644 --- a/gnucash/import-export/aqb/test/test-kvp.c +++ b/gnucash/import-export/aqb/test/test-kvp.c @@ -64,7 +64,7 @@ test_qofsession_aqb_kvp( void ) if (1) { // A file with no content at all, but a valid XML file - QofSession *new_session = qof_session_new (); + QofSession *new_session = qof_session_new (NULL); char *newfile = g_strdup_printf("file://%s", file1); qof_session_begin (new_session, newfile, TRUE, FALSE, FALSE); @@ -92,7 +92,7 @@ test_qofsession_aqb_kvp( void ) { // A file with no content except for the book_template_list kvp // slot - QofSession *new_session = qof_session_new (); + QofSession *new_session = qof_session_new (NULL); char *newfile = g_strdup_printf("file://%s", file2); qof_session_begin (new_session, newfile, TRUE, FALSE, FALSE); diff --git a/libgnucash/backend/dbi/test/test-backend-dbi-basic.cpp b/libgnucash/backend/dbi/test/test-backend-dbi-basic.cpp index 4980adb765..c824959b34 100644 --- a/libgnucash/backend/dbi/test/test-backend-dbi-basic.cpp +++ b/libgnucash/backend/dbi/test/test-backend-dbi-basic.cpp @@ -91,7 +91,7 @@ setup (Fixture* fixture, gconstpointer pData) { gchar* url = (gchar*)pData; gnc_module_init_backend_dbi(); - fixture->session = qof_session_new (); + fixture->session = qof_session_new (nullptr); /* When running distcheck the source directory is read-only, which * prevents creating the lock file. Force the session to get * around that. @@ -111,9 +111,9 @@ setup (Fixture* fixture, gconstpointer pData) static void setup_memory (Fixture* fixture, gconstpointer pData) { - QofSession* session = nullptr; gchar* url = (gchar*)pData; - QofBook* book; + auto book = qof_book_new(); + auto session = qof_session_new (book); Account* root, *acct1, *acct2; Transaction* tx; Split* spl1, *spl2; @@ -121,8 +121,6 @@ setup_memory (Fixture* fixture, gconstpointer pData) gnc_commodity* currency; gnc_module_init_backend_dbi(); - session = qof_session_new (); - book = qof_session_get_book (session); root = gnc_book_get_root_account (book); table = gnc_commodity_table_get_table (book); @@ -170,9 +168,9 @@ static void setup_business (Fixture* fixture, gconstpointer pData) { gnc_module_init_backend_dbi (); - QofSession* session = qof_session_new (); + auto book = qof_book_new (); + auto session = qof_session_new (book); gchar* url = (gchar*)pData; - QofBook* book = qof_session_get_book (session); Account* root = gnc_book_get_root_account (book); Account* acct1; Account* acct2; @@ -382,9 +380,6 @@ test_dbi_store_and_reload (Fixture* fixture, gconstpointer pData) { const gchar* url = (const gchar*)pData; - QofSession* session_2; - QofSession* session_3; - auto msg = "[GncDbiSqlConnection::unlock_database()] There was no lock entry in the Lock table"; auto log_domain = nullptr; auto loglevel = static_cast (G_LOG_LEVEL_WARNING | @@ -396,7 +391,7 @@ test_dbi_store_and_reload (Fixture* fixture, gconstpointer pData) url = fixture->filename; // Save the session data - session_2 = qof_session_new (); + auto session_2 = qof_session_new (nullptr); qof_session_begin (session_2, url, FALSE, TRUE, TRUE); g_assert (session_2 != NULL); g_assert_cmpint (qof_session_get_error (session_2), == , ERR_BACKEND_NO_ERR); @@ -407,7 +402,7 @@ test_dbi_store_and_reload (Fixture* fixture, gconstpointer pData) g_assert_cmpint (qof_session_get_error (session_2), == , ERR_BACKEND_NO_ERR); // Reload the session data - session_3 = qof_session_new (); + auto session_3 = qof_session_new (nullptr); g_assert (session_3 != NULL); qof_session_begin (session_3, url, TRUE, FALSE, FALSE); g_assert (session_3 != NULL); @@ -436,8 +431,7 @@ static void test_dbi_safe_save (Fixture* fixture, gconstpointer pData) { auto url = (gchar*)pData; - QofSession* session_1 = NULL, *session_2 = NULL; - + QofSession* session_2 = nullptr; // Otherwise goto cleanup bypasses init. auto msg = "[GncDbiSqlConnection::unlock_database()] There was no lock entry in the Lock table"; auto log_domain = nullptr; auto loglevel = static_cast (G_LOG_LEVEL_WARNING | @@ -448,7 +442,7 @@ test_dbi_safe_save (Fixture* fixture, gconstpointer pData) url = fixture->filename; // Load the session data - session_1 = qof_session_new (); + auto session_1 = qof_session_new (nullptr); qof_session_begin (session_1, url, FALSE, TRUE, TRUE); if (session_1 && qof_session_get_error (session_1) != ERR_BACKEND_NO_ERR) @@ -474,7 +468,7 @@ test_dbi_safe_save (Fixture* fixture, gconstpointer pData) } /* Destroy the session and reload it */ - session_2 = qof_session_new (); + session_2 = qof_session_new (nullptr); qof_session_begin (session_2, url, TRUE, FALSE, FALSE); if (session_2 && qof_session_get_error (session_2) != ERR_BACKEND_NO_ERR) @@ -514,8 +508,7 @@ static void test_dbi_version_control (Fixture* fixture, gconstpointer pData) { auto url = (gchar*)pData; - QofSession* sess; - QofBook* book; + QofBook* book = nullptr; QofBackendError err; gint ourversion = gnc_prefs_get_long_version (); GncSqlBackend* sql_be = nullptr; @@ -523,7 +516,7 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData) // Load the session data if (fixture->filename) url = fixture->filename; - sess = qof_session_new (); + auto sess = qof_session_new (nullptr); qof_session_begin (sess, url, FALSE, TRUE, TRUE); if (sess && qof_session_get_error (sess) != ERR_BACKEND_NO_ERR) { @@ -543,7 +536,7 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData) qof_book_commit_edit (book); qof_session_end (sess); qof_session_destroy (sess); - sess = qof_session_new (); + sess = qof_session_new (nullptr); qof_session_begin (sess, url, TRUE, FALSE, FALSE); qof_session_load (sess, NULL); err = qof_session_pop_error (sess); @@ -556,7 +549,7 @@ test_dbi_version_control (Fixture* fixture, gconstpointer pData) qof_book_commit_edit (book); qof_session_end (sess); qof_session_destroy (sess); - sess = qof_session_new (); + sess = qof_session_new (nullptr); qof_session_begin (sess, url, TRUE, FALSE, FALSE); qof_session_load (sess, NULL); qof_session_ensure_all_data_loaded (sess); @@ -575,8 +568,6 @@ cleanup: static void test_dbi_business_store_and_reload (Fixture* fixture, gconstpointer pData) { - QofSession* session_2; - QofSession* session_3; const gchar* url = (gchar*)pData; auto msg = "[GncDbiSqlConnection::unlock_database()] There was no lock entry in the Lock table"; @@ -587,14 +578,14 @@ test_dbi_business_store_and_reload (Fixture* fixture, gconstpointer pData) if (fixture->filename) url = fixture->filename; // Save the session data - session_2 = qof_session_new (); + auto session_2 = qof_session_new (nullptr); qof_session_begin (session_2, url, FALSE, TRUE, TRUE); qof_session_swap_data (fixture->session, session_2); qof_book_mark_session_dirty (qof_session_get_book (session_2)); qof_session_save (session_2, NULL); // Reload the session data - session_3 = qof_session_new (); + auto session_3 = qof_session_new (nullptr); qof_session_begin (session_3, url, TRUE, FALSE, FALSE); qof_session_load (session_3, NULL); diff --git a/libgnucash/backend/xml/test/test-load-xml2.cpp b/libgnucash/backend/xml/test/test-load-xml2.cpp index f417fd6c2b..2daa106c22 100644 --- a/libgnucash/backend/xml/test/test-load-xml2.cpp +++ b/libgnucash/backend/xml/test/test-load-xml2.cpp @@ -83,9 +83,6 @@ remove_locks (const char* filename) static void test_load_file (const char* filename) { - QofSession* session; - QofBook* book; - Account* root; gboolean ignore_lock; const char* logdomain = "backend.xml"; GLogLevelFlags loglevel = static_cast @@ -94,7 +91,7 @@ test_load_file (const char* filename) g_log_set_handler (logdomain, loglevel, (GLogFunc)test_checked_handler, &check); - session = qof_session_new (); + auto session = qof_session_new (nullptr); remove_locks (filename); @@ -103,9 +100,9 @@ test_load_file (const char* filename) qof_session_begin (session, filename, ignore_lock, FALSE, TRUE); qof_session_load (session, NULL); - book = qof_session_get_book (session); + auto book = qof_session_get_book (session); - root = gnc_book_get_root_account (book); + auto root = gnc_book_get_root_account (book); do_test (gnc_account_get_book (root) == book, "book and root account don't match"); diff --git a/libgnucash/backend/xml/test/test-save-in-lang.cpp b/libgnucash/backend/xml/test/test-save-in-lang.cpp index 670534831f..e6a3919b64 100644 --- a/libgnucash/backend/xml/test/test-save-in-lang.cpp +++ b/libgnucash/backend/xml/test/test-save-in-lang.cpp @@ -97,9 +97,8 @@ test_file (const char* filename) QofSession* session; char* cmd; char* new_file = gen_new_file_name (filename, possible_envs[i]); - QofSession* new_session; - session = qof_session_new (); + auto session = qof_session_new (nullptr); qof_session_begin (session, filename, TRUE, FALSE, FALSE); err = qof_session_pop_error (session); @@ -120,7 +119,7 @@ test_file (const char* filename) if (!g_setenv ("LANG", possible_envs[i], TRUE)) return g_strdup ("setenv for LANG"); - new_session = qof_session_new (); + auto new_session = qof_session_new (nullptr); qof_session_begin (new_session, new_file, FALSE, FALSE, FALSE); err = qof_session_pop_error (new_session); diff --git a/libgnucash/backend/xml/test/test-xml-account.cpp b/libgnucash/backend/xml/test/test-xml-account.cpp index 5022a9143c..d336ec2372 100644 --- a/libgnucash/backend/xml/test/test-xml-account.cpp +++ b/libgnucash/backend/xml/test/test-xml-account.cpp @@ -386,12 +386,11 @@ test_real_account (const char* tag, gpointer global_data, gpointer data) int main (int argc, char** argv) { - QofSession* session; qof_init (); cashobjects_register (); - session = qof_session_new (); - sixbook = qof_session_get_book (session); + sixbook = qof_book_new (); + auto session = qof_session_new (sixbook); if (argc > 1) { test_files_in_dir (argc, argv, test_real_account, diff --git a/libgnucash/backend/xml/test/test-xml-pricedb.cpp b/libgnucash/backend/xml/test/test-xml-pricedb.cpp index 18d22ef6b8..4660084f7b 100644 --- a/libgnucash/backend/xml/test/test-xml-pricedb.cpp +++ b/libgnucash/backend/xml/test/test-xml-pricedb.cpp @@ -46,7 +46,7 @@ extern "C" #include "test-file-stuff.h" #include "test-stuff.h" -static QofSession* session; +static QofSession* session = NULL; static int iter; static gboolean @@ -126,9 +126,10 @@ test_generation (void) for (iter = 0; iter < 20; iter++) { GNCPriceDB* db; + auto book = qof_book_new(); g_message ("iter=%d", iter); - session = qof_session_new (); - db = get_random_pricedb (qof_session_get_book (session)); + session = qof_session_new (book); + db = get_random_pricedb (book); if (!db) { failure_args ("gnc_random_price_db returned NULL", @@ -151,7 +152,6 @@ main (int argc, char** argv) //qof_log_init_filename("/tmp/gnctest.trace"); //qof_log_set_default(QOF_LOG_DETAIL); //qof_log_set_level(GNC_MOD_PRICE, QOF_LOG_DETAIL); - session = qof_session_new (); test_generation (); print_test_results (); qof_close (); diff --git a/libgnucash/engine/gnc-session.c b/libgnucash/engine/gnc-session.c index 6df5868b18..7bc674c537 100644 --- a/libgnucash/engine/gnc-session.c +++ b/libgnucash/engine/gnc-session.c @@ -35,8 +35,9 @@ gnc_get_current_session (void) { if (!current_session) { + QofBook* book = qof_book_new (); qof_event_suspend(); - current_session = qof_session_new (); + current_session = qof_session_new (book); qof_event_resume(); } diff --git a/libgnucash/engine/qofsession.cpp b/libgnucash/engine/qofsession.cpp index a42ad09123..1db4b6b54a 100644 --- a/libgnucash/engine/qofsession.cpp +++ b/libgnucash/engine/qofsession.cpp @@ -118,8 +118,9 @@ qof_backend_get_registered_access_method_list(void) /* ====================================================================== */ /* Constructor/Destructor ----------------------------------*/ -QofSessionImpl::QofSessionImpl () noexcept - : m_book {qof_book_new ()}, +QofSessionImpl::QofSessionImpl (QofBook* book) noexcept + : m_backend {}, + m_book {book}, m_book_id {}, m_saving {false}, m_last_err {}, @@ -145,19 +146,19 @@ qof_session_destroy (QofSession * session) } QofSession * -qof_session_new (void) +qof_session_new (QofBook* book) { - return new QofSessionImpl; + return new QofSessionImpl(book); } void QofSessionImpl::destroy_backend () noexcept { - auto backend = qof_book_get_backend (m_book); - if (backend) + if (m_backend) { clear_error (); - delete backend; + delete m_backend; + m_backend = nullptr; qof_book_set_backend (m_book, nullptr); } } @@ -187,8 +188,7 @@ QofSessionImpl::load_backend (std::string access_method) noexcept prov->provider_name, m_book_id.c_str ()); continue; } - auto backend = prov->create_backend(); - qof_book_set_backend (m_book, backend); + m_backend = prov->create_backend(); LEAVE (" "); return; } @@ -209,12 +209,25 @@ QofSessionImpl::load (QofPercentageFunc percentage_func) noexcept /* At this point, we should are supposed to have a valid book * id and a lock on the file. */ clear_error (); - auto be (qof_book_get_backend(m_book)); - if (be) + + /* This code should be sufficient to initialize *any* backend, + * whether http, postgres, or anything else that might come along. + * Basically, the idea is that by now, a backend has already been + * created & set up. At this point, we only need to get the + * top-level account group out of the backend, and that is a + * generic, backend-independent operation. + */ + qof_book_set_backend (newbook, m_backend); + + /* Starting the session should result in a bunch of accounts + * and currencies being downloaded, but probably no transactions; + * The GUI will need to do a query for that. + */ + if (m_backend) { - be->set_percentage(percentage_func); - be->load (m_book, LOAD_TYPE_INITIAL_LOAD); - push_error (be->get_error(), {}); + m_backend->set_percentage(percentage_func); + m_backend->load (newbook, LOAD_TYPE_INITIAL_LOAD); + push_error (m_backend->get_error(), {}); } auto err = get_error (); @@ -225,12 +238,17 @@ QofSessionImpl::load (QofPercentageFunc percentage_func) noexcept (err != ERR_SQL_DB_TOO_OLD) && (err != ERR_SQL_DB_TOO_NEW)) { - auto old_book = m_book; - m_book = qof_book_new(); - qof_book_destroy(old_book); + /* Something broke, put back the old stuff */ + delete m_backend; + qof_book_set_backend (newbook, NULL); + qof_book_destroy (newbook); + m_book = oldbook; + m_backend = qof_book_get_backend (m_book); LEAVE ("error from backend %d", get_error ()); return; } + qof_book_destroy (oldbook); + LEAVE ("sess = %p, book_id=%s", this, m_book_id.c_str ()); } @@ -288,8 +306,7 @@ QofSessionImpl::begin (std::string new_book_id, bool ignore_lock, g_free (scheme); /* No backend was found. That's bad. */ - auto backend = qof_book_get_backend (m_book); - if (backend == nullptr) + if (m_backend == nullptr) { m_book_id = {}; if (ERR_BACKEND_NO_ERR == get_error ()) @@ -300,10 +317,11 @@ QofSessionImpl::begin (std::string new_book_id, bool ignore_lock, } /* If there's a begin method, call that. */ - backend->session_begin(this, m_book_id.c_str(), ignore_lock, create, force); + m_backend->session_begin(this, m_book_id.c_str(), + ignore_lock, create, force); PINFO ("Done running session_begin on backend"); - QofBackendError const err {backend->get_error()}; - auto msg (backend->get_message()); + QofBackendError const err {m_backend->get_error()}; + auto msg (m_backend->get_message()); if (err != ERR_BACKEND_NO_ERR) { m_book_id = {}; @@ -397,7 +415,7 @@ QofSessionImpl::get_book () const noexcept QofBackend * QofSession::get_backend () const noexcept { - return qof_book_get_backend (m_book); + return m_backend; } std::string @@ -436,13 +454,14 @@ QofSessionImpl::save (QofPercentageFunc percentage_func) noexcept * network has crashed, etc.) then raise an error so that the controlling * dialog can offer the user a chance to save in a different way. */ - auto backend = qof_book_get_backend (m_book); - if (backend) + if (m_backend) { - - backend->set_percentage(percentage_func); - backend->sync(m_book); - auto err = backend->get_error(); + /* if invoked as SaveAs(), then backend not yet set */ + if (qof_book_get_backend (m_book) != m_backend) + qof_book_set_backend (m_book, m_backend); + m_backend->set_percentage(percentage_func); + m_backend->sync(m_book); + auto err = m_backend->get_error(); if (err != ERR_BACKEND_NO_ERR) { push_error (err, {}); @@ -465,12 +484,13 @@ QofSessionImpl::save (QofPercentageFunc percentage_func) noexcept void QofSessionImpl::safe_save (QofPercentageFunc percentage_func) noexcept { - auto backend = qof_book_get_backend (m_book); - if (!backend) return; - backend->set_percentage(percentage_func); - backend->safe_sync(get_book ()); - auto err = backend->get_error(); - auto msg = backend->get_message(); + if (!(m_backend && m_book)) return; + if (qof_book_get_backend (m_book) != m_backend) + qof_book_set_backend (m_book, m_backend); + m_backend->set_percentage(percentage_func); + m_backend->safe_sync(get_book ()); + auto err = m_backend->get_error(); + auto msg = m_backend->get_message(); if (err != ERR_BACKEND_NO_ERR) { m_book_id = nullptr; @@ -481,10 +501,11 @@ QofSessionImpl::safe_save (QofPercentageFunc percentage_func) noexcept void QofSessionImpl::ensure_all_data_loaded () noexcept { - auto backend = qof_book_get_backend (m_book); - if (!backend) return; - backend->load(m_book, LOAD_TYPE_LOAD_ALL); - push_error (backend->get_error(), {}); + if (!(m_backend && m_book)) return; + if (qof_book_get_backend (m_book) != m_backend) + qof_book_set_backend (m_book, m_backend); + m_backend->load(m_book, LOAD_TYPE_LOAD_ALL); + push_error (m_backend->get_error(), {}); } void @@ -492,7 +513,8 @@ QofSessionImpl::swap_books (QofSessionImpl & other) noexcept { ENTER ("sess1=%p sess2=%p", this, &other); // don't swap (that is, double-swap) read_only flags - std::swap (m_book->read_only, other.m_book->read_only); + if (m_book && other.m_book) + std::swap (m_book->read_only, other.m_book->read_only); std::swap (m_book, other.m_book); auto mybackend = qof_book_get_backend (m_book); qof_book_set_backend (m_book, qof_book_get_backend (other.m_book)); @@ -527,13 +549,12 @@ QofSessionImpl::export_session (QofSessionImpl & real_session, /* There must be a backend or else. (It should always be the file * backend too.) */ - auto backend2 = qof_book_get_backend(m_book); - if (!backend2) return false; + if (!m_backend) return false; - backend2->set_percentage(percentage_func); + m_backend->set_percentage(percentage_func); - backend2->export_coa(real_book); - auto err = backend2->get_error(); + m_backend->export_coa(real_book); + auto err = m_backend->get_error(); if (err != ERR_BACKEND_NO_ERR) return false; return true; diff --git a/libgnucash/engine/qofsession.h b/libgnucash/engine/qofsession.h index dafa437561..88b7b25468 100644 --- a/libgnucash/engine/qofsession.h +++ b/libgnucash/engine/qofsession.h @@ -114,7 +114,7 @@ extern "C" typedef struct QofSessionImpl QofSession; -QofSession * qof_session_new (void); +QofSession * qof_session_new (QofBook* book); void qof_session_destroy (QofSession *session); /** The qof_session_swap_data () method swaps the book of diff --git a/libgnucash/engine/qofsession.hpp b/libgnucash/engine/qofsession.hpp index 7820e08caa..12a92b16bb 100644 --- a/libgnucash/engine/qofsession.hpp +++ b/libgnucash/engine/qofsession.hpp @@ -36,7 +36,7 @@ struct QofSessionImpl { - QofSessionImpl () noexcept; + QofSessionImpl (QofBook* book = nullptr) noexcept; /* Ends the current session, destroys the backend, and destroys the book. */ ~QofSessionImpl () noexcept; @@ -85,10 +85,13 @@ private: void load_backend (std::string access_method) noexcept; + /* The backend. We store this during startup to avoid having to create a + * book just to hold it. + */ + QofBackend* m_backend; /* A book holds pointers to the various types of datasets. * A session has exactly one book. */ QofBook * m_book; - /* The requested book id, in the form or a URI, such as * file:/some/where, or sql:server.host.com:555 */ diff --git a/libgnucash/engine/test-core/test-engine-stuff.cpp b/libgnucash/engine/test-core/test-engine-stuff.cpp index 13ec7af8da..bd0b862163 100644 --- a/libgnucash/engine/test-core/test-engine-stuff.cpp +++ b/libgnucash/engine/test-core/test-engine-stuff.cpp @@ -1875,12 +1875,8 @@ get_random_book (void) QofSession * get_random_session (void) { - QofSession *session; - QofBook *book; - - session = qof_session_new (); - - book = qof_session_get_book (session); + auto book = qof_book_new (); + auto session = qof_session_new (book); get_random_account_tree (book); get_random_pricedb (book); diff --git a/libgnucash/engine/test/test-qofsession-old.cpp b/libgnucash/engine/test/test-qofsession-old.cpp index 20dc52078c..d9be207f36 100644 --- a/libgnucash/engine/test/test-qofsession-old.cpp +++ b/libgnucash/engine/test/test-qofsession-old.cpp @@ -70,7 +70,7 @@ percentage_fn ( const char* message, double percent ) static void setup( Fixture *fixture, gconstpointer pData ) { - fixture->session = qof_session_new(); + fixture->session = qof_session_new (qof_book_new ()); init_static_qofsession_pointers (); g_assert (p_qof_session_clear_error && p_qof_session_destroy_backend && p_qof_session_load_backend); } @@ -87,14 +87,11 @@ teardown( Fixture *fixture, gconstpointer pData ) static void test_qof_session_new_destroy (void) { - QofSession *session = NULL; - QofBook *book = NULL; - g_test_message ("Test session initialization"); - session = qof_session_new (); + auto session = qof_session_new (qof_book_new ()); g_assert (session); g_assert (qof_session_get_book (session)); - book = (QofBook*) qof_session_get_book (session); + auto book = qof_session_get_book (session); g_assert (book); g_assert (QOF_IS_BOOK (book)); g_assert (!strlen (qof_session_get_url (session))); @@ -584,11 +581,9 @@ mock_export (QofBackend *be, QofBook *book) static void test_qof_session_export (Fixture *fixture, gconstpointer pData) { - QofSession *real_session = NULL; - QofBook *tmp_book = NULL, *real_book = NULL; QofBackend *be = NULL; - real_session = qof_session_new (); + auto real_session = qof_session_new (qof_book_new ()); g_assert (real_session); g_test_message ("Test null checks"); @@ -596,9 +591,9 @@ test_qof_session_export (Fixture *fixture, gconstpointer pData) g_assert (!qof_session_export (fixture->session, NULL, percentage_fn)); g_test_message ("Test with backend not set"); - tmp_book = qof_session_get_book (fixture->session); + auto tmp_book = qof_session_get_book (fixture->session); g_assert (tmp_book); - be = qof_book_get_backend (tmp_book); + auto be = qof_book_get_backend (tmp_book); g_assert (!be); g_assert (!qof_session_export (fixture->session, real_session, percentage_fn)); @@ -616,7 +611,7 @@ test_qof_session_export (Fixture *fixture, gconstpointer pData) qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT); qof_backend_set_message (be, "push any error"); session_export_struct.called = FALSE; - real_book = qof_session_get_book (real_session); + auto real_book = qof_session_get_book (real_session); g_assert (real_book); session_export_struct.be = be; session_export_struct.book = real_book; @@ -641,7 +636,7 @@ test_qof_session_swap_data (Fixture *fixture, gconstpointer pData) /* init */ g_assert (fixture->session); - session2 = qof_session_new (); + auto session2 = qof_session_new (qof_book_new ()); g_assert (session2); g_assert (fixture->session != session2); be1 = g_new0 (QofBackend, 1); diff --git a/libgnucash/engine/test/test-qofsession.cpp b/libgnucash/engine/test/test-qofsession.cpp index fd53b1ce2c..ae9b57311f 100644 --- a/libgnucash/engine/test/test-qofsession.cpp +++ b/libgnucash/engine/test/test-qofsession.cpp @@ -105,9 +105,9 @@ get_provider () TEST (QofSessionTest, swap_books) { qof_backend_register_provider (get_provider ()); - QofSession s1; + QofSession s1(qof_book_new()); s1.begin ("book1", false, false, false); - QofSession s2; + QofSession s2(qof_book_new()); s2.begin ("book2", false, false, false); QofBook * b1 {s1.get_book ()}; QofBook * b2 {s2.get_book ()}; @@ -121,7 +121,7 @@ TEST (QofSessionTest, swap_books) TEST (QofSessionTest, ensure_all_data_loaded) { qof_backend_register_provider (get_provider ()); - QofSession s; + QofSession s(qof_book_new()); s.begin ("book1", false, false, false); data_loaded = false; s.ensure_all_data_loaded (); @@ -132,7 +132,7 @@ TEST (QofSessionTest, ensure_all_data_loaded) TEST (QofSessionTest, get_error) { qof_backend_register_provider (get_provider ()); - QofSession s; + QofSession s(qof_book_new()); s.begin ("book1", false, false, false); s.ensure_all_data_loaded (); EXPECT_NE (s.get_error (), ERR_BACKEND_NO_ERR); @@ -144,7 +144,7 @@ TEST (QofSessionTest, get_error) TEST (QofSessionTest, pop_error) { qof_backend_register_provider (get_provider ()); - QofSession s; + QofSession s(qof_book_new()); s.begin ("book1", false, false, false); //We run the test first, and make sure there is an error condition. s.ensure_all_data_loaded (); @@ -156,7 +156,7 @@ TEST (QofSessionTest, pop_error) TEST (QofSessionTest, clear_error) { qof_backend_register_provider (get_provider ()); - QofSession s; + QofSession s(qof_book_new()); s.begin ("book1", false, false, false); //We run the test first, and make sure there is an error condition. s.ensure_all_data_loaded (); @@ -199,7 +199,7 @@ TEST (QofSessionTest, load) TEST (QofSessionTest, save) { qof_backend_register_provider (get_provider ()); - QofSession s; + QofSession s(qof_book_new()); s.begin ("book1", false, false, false); load_error = false; s.load (nullptr); @@ -214,7 +214,7 @@ TEST (QofSessionTest, save) TEST (QofSessionTest, safe_save) { qof_backend_register_provider (get_provider ()); - QofSession s; + QofSession s(qof_book_new()); s.begin ("book1", false, false, false); s.safe_save (nullptr); EXPECT_EQ (safe_sync_called, true); @@ -225,14 +225,14 @@ TEST (QofSessionTest, safe_save) TEST (QofSessionTest, export_session) { qof_backend_register_provider (get_provider ()); - QofSession s1; + auto b1 = qof_book_new(); + QofSession s1(b1); s1.begin ("book1", false, false, false); - QofSession s2; + qof_book_set_backend(b1, s1.get_backend()); + auto b2 = qof_book_new(); + QofSession s2(b2); s2.begin ("book2", false, false, false); - QofBook * b1 = s1.get_book (); - QofBook * b2 = s2.get_book (); - b1->backend = s1.get_backend (); - b2->backend = s2.get_backend (); + qof_book_set_backend(b2, s2.get_backend()); s2.export_session (s1, nullptr); EXPECT_EQ (exported_book, b1); diff --git a/libgnucash/engine/test/test-split-vs-account.cpp b/libgnucash/engine/test/test-split-vs-account.cpp index d51ac2a082..ee1e320a11 100644 --- a/libgnucash/engine/test/test-split-vs-account.cpp +++ b/libgnucash/engine/test/test-split-vs-account.cpp @@ -38,19 +38,12 @@ extern "C" static void run_test (void) { - Account *act1; - Account *act2; - //Split *spl; - QofSession *session; - QofBook *book; + auto book = qof_book_new (); - session = qof_session_new (); - book = qof_session_get_book (session); - - act1 = get_random_account(book); + auto act1 = get_random_account(book); do_test(act1 != NULL, "random account created"); - act2 = get_random_account(book); + auto act2 = get_random_account(book); do_test(act2 != NULL, "random account created"); #if 0 spl = get_random_split(book, act1, NULL);