LCOV - code coverage report
Current view: top level - libgnucash/engine - qofsession.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 66.7 % 327 218
Test Date: 2026-11-02 18:19:43 Functions: 58.2 % 55 32
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /********************************************************************\
       2              :  * qofsession.cpp -- session access (connection to backend)        *
       3              :  *                                                                  *
       4              :  * This program is free software; you can redistribute it and/or    *
       5              :  * modify it under the terms of the GNU General Public License as   *
       6              :  * published by the Free Software Foundation; either version 2 of   *
       7              :  * the License, or (at your option) any later version.              *
       8              :  *                                                                  *
       9              :  * This program is distributed in the hope that it will be useful,  *
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      12              :  * GNU General Public License for more details.                     *
      13              :  *                                                                  *
      14              :  * You should have received a copy of the GNU General Public License*
      15              :  * along with this program; if not, contact:                        *
      16              :  *                                                                  *
      17              :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      18              :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      19              :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      20              : \********************************************************************/
      21              : 
      22              : /**
      23              :  * @file qofsession.cpp
      24              :  * @brief Encapsulate a connection to a storage backend.
      25              :  *
      26              :  * HISTORY:
      27              :  * Created by Linas Vepstas December 1998
      28              : 
      29              :  @author Copyright (c) 1998-2004 Linas Vepstas <linas@linas.org>
      30              :  @author Copyright (c) 2000 Dave Peticolas
      31              :  @author Copyright (c) 2005 Neil Williams <linux@codehelp.co.uk>
      32              :  @author Copyright (c) 2016 Aaron Laws
      33              :    */
      34              : #include <glib.h>
      35              : 
      36              : #include <config.h>
      37              : 
      38              : #include <stdlib.h>
      39              : #include <sys/types.h>
      40              : #include <sys/stat.h>
      41              : #ifdef HAVE_UNISTD_H
      42              : # include <unistd.h>
      43              : #else
      44              : # ifdef __GNUC__
      45              : #  warning "<unistd.h> required."
      46              : # endif
      47              : #endif
      48              : 
      49              : #include "qof.h"
      50              : #include "qofobject-p.h"
      51              : 
      52              : static QofLogModule log_module = QOF_MOD_SESSION;
      53              : 
      54              : #include "qofbook-p.hpp"
      55              : #include "qof-backend.hpp"
      56              : #include "qofsession.hpp"
      57              : #include "gnc-backend-prov.hpp"
      58              : #include "gnc-uri-utils.h"
      59              : 
      60              : #include <vector>
      61              : #include <boost/algorithm/string.hpp>
      62              : #include <vector>
      63              : #include <algorithm>
      64              : #include <string>
      65              : #include <sstream>
      66              : 
      67              : using ProviderVec =  std::vector<QofBackendProvider_ptr>;
      68              : static ProviderVec s_providers;
      69              : static const std::string empty_string{};
      70              : /*
      71              :  * These getters are used in tests to reach static vars from outside
      72              :  * They should be removed when no longer needed
      73              :  */
      74              : 
      75              : ProviderVec& get_providers (void );
      76              : bool get_providers_initialized (void );
      77              : 
      78              : ProviderVec&
      79            0 : get_providers (void)
      80              : {
      81            0 :     return s_providers;
      82              : }
      83              : 
      84              : bool
      85            0 : get_providers_initialized (void)
      86              : {
      87            0 :     return !s_providers.empty();
      88              : }
      89              : 
      90              : void
      91           62 : qof_backend_register_provider (QofBackendProvider_ptr&& prov)
      92              : {
      93           62 :     s_providers.emplace_back(std::move(prov));
      94           62 : }
      95              : 
      96              : void
      97            0 : qof_backend_unregister_all_providers ()
      98              : {
      99            0 :     s_providers.clear ();
     100            0 : }
     101              : 
     102              : /* Called from C so we have to keep the GList for now. */
     103              : GList*
     104            6 : qof_backend_get_registered_access_method_list(void)
     105              : {
     106            6 :     GList* list = NULL;
     107            6 :     std::for_each(s_providers.begin(), s_providers.end(),
     108            0 :                   [&list](QofBackendProvider_ptr& provider) {
     109            0 :                       gpointer method = reinterpret_cast<gpointer>(const_cast<char*>(provider->access_method));
     110            0 :                       list = g_list_prepend(list, method);
     111            0 :                   });
     112            6 :     return list;
     113              : }
     114              : 
     115              : /* QofSessionImpl */
     116              : /* ====================================================================== */
     117              : /* Constructor/Destructor ----------------------------------*/
     118              : 
     119          290 : QofSessionImpl::QofSessionImpl (QofBook* book) noexcept
     120          290 :   : m_backend {},
     121          290 :     m_book {book},
     122          290 :     m_uri {},
     123          290 :     m_saving {false},
     124          290 :     m_last_err {},
     125          290 :     m_error_message {}
     126              : {
     127          290 : }
     128              : 
     129          165 : QofSessionImpl::~QofSessionImpl () noexcept
     130              : {
     131          165 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     132          165 :     end ();
     133          165 :     destroy_backend ();
     134          165 :     qof_book_set_backend (m_book, nullptr);
     135          165 :     qof_book_destroy (m_book);
     136          165 :     m_book = nullptr;
     137          165 :     LEAVE ("sess=%p", this);
     138          165 : }
     139              : 
     140              : void
     141          165 : qof_session_destroy (QofSession * session)
     142              : {
     143          165 :     delete session;
     144          165 : }
     145              : 
     146              : QofSession *
     147          290 : qof_session_new (QofBook* book)
     148              : {
     149          290 :     return new QofSessionImpl(book);
     150              : }
     151              : 
     152              : void
     153          212 : QofSessionImpl::destroy_backend () noexcept
     154              : {
     155          212 :     if (m_backend)
     156              :     {
     157           30 :         clear_error ();
     158           30 :         delete m_backend;
     159           30 :         m_backend = nullptr;
     160           30 :         qof_book_set_backend (m_book, nullptr);
     161              :     }
     162          212 : }
     163              : 
     164              : /* ====================================================================== */
     165              : 
     166              : void
     167           47 : QofSessionImpl::load_backend (std::string access_method) noexcept
     168              : {
     169           47 :     std::ostringstream s;
     170           47 :     s << " list=" << s_providers.size();
     171           47 :     ENTER ("%s", s.str().c_str());
     172          136 :     for (auto const & prov : s_providers)
     173              :     {
     174           88 :         if (!boost::iequals (access_method, prov->access_method))
     175              :         {
     176           39 :             PINFO ("The provider providers access_method, %s, but we're loading for access_method, %s. Skipping.",
     177              :                     prov->access_method, access_method.c_str ());
     178           39 :             continue;
     179              :         }
     180           49 :         PINFO (" Selected provider %s", prov->provider_name);
     181              :         // Only do a type check when trying to open an existing file
     182              :         // When saving over an existing file the contents of the original file don't matter
     183           49 :         if (!m_creating && !prov->type_check (m_uri.c_str ()))
     184              :         {
     185            3 :             PINFO("Provider, %s, reported not being usable for book, %s.",
     186              :                     prov->provider_name, m_uri.c_str ());
     187            3 :             continue;
     188              :         }
     189           46 :         m_backend = prov->create_backend();
     190           46 :         LEAVE (" ");
     191           46 :         return;
     192              :     }
     193            1 :     std::string msg {"failed to get_backend using access method \"" + access_method + "\""};
     194            1 :     push_error (ERR_BACKEND_NO_HANDLER, msg);
     195            1 :     LEAVE (" ");
     196           47 : }
     197              : 
     198              : void
     199           30 : QofSessionImpl::load (QofPercentageFunc percentage_func) noexcept
     200              : {
     201              :     /* We must have an empty book to load into or bad things will happen. */
     202           30 :     g_return_if_fail(m_book && qof_book_empty(m_book));
     203              : 
     204           29 :     if (!m_uri.size ()) return;
     205           29 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     206              : 
     207              :     /* At this point, we should are supposed to have a valid book
     208              :      * id and a lock on the file. */
     209           29 :     clear_error ();
     210              : 
     211              :     /* This code should be sufficient to initialize *any* backend,
     212              :      * whether http, postgres, or anything else that might come along.
     213              :      * Basically, the idea is that by now, a backend has already been
     214              :      * created & set up.  At this point, we only need to get the
     215              :      * top-level account group out of the backend, and that is a
     216              :      * generic, backend-independent operation.
     217              :      */
     218           29 :     qof_book_set_backend (m_book, m_backend);
     219              : 
     220              :     /* Starting the session should result in a bunch of accounts
     221              :      * and currencies being downloaded, but probably no transactions;
     222              :      * The GUI will need to do a query for that.
     223              :      */
     224           29 :     if (m_backend)
     225              :     {
     226           29 :         m_backend->set_percentage(percentage_func);
     227           29 :         m_backend->load (m_book, LOAD_TYPE_INITIAL_LOAD);
     228           29 :         push_error (m_backend->get_error(), {});
     229              :     }
     230              : 
     231           29 :     auto err = get_error ();
     232           29 :     if ((err != ERR_BACKEND_NO_ERR) &&
     233            2 :         (err != ERR_FILEIO_FILE_TOO_OLD) &&
     234            2 :         (err != ERR_FILEIO_NO_ENCODING) &&
     235            2 :         (err != ERR_FILEIO_FILE_UPGRADE) &&
     236            1 :         (err != ERR_SQL_DB_TOO_OLD) &&
     237              :         (err != ERR_SQL_DB_TOO_NEW))
     238              :     {
     239              :         // Something failed, delete and restore new ones.
     240            0 :         destroy_backend();
     241            0 :         qof_book_destroy (m_book);
     242            0 :         m_book = qof_book_new();
     243            0 :         LEAVE ("error from backend %d", get_error ());
     244            0 :         return;
     245              :     }
     246              : 
     247           29 :     LEAVE ("sess = %p, uri=%s", this, m_uri.c_str ());
     248              : }
     249              : 
     250              : void
     251           47 : QofSessionImpl::begin (const char* new_uri, SessionOpenMode mode) noexcept
     252              : {
     253              : 
     254              : 
     255           47 :     ENTER (" sess=%p mode=%d, URI=%s", this, mode, new_uri);
     256           47 :     clear_error ();
     257              :     /* Check to see if this session is already open */
     258           47 :     if (m_uri.size ())
     259              :     {
     260            0 :         if (ERR_BACKEND_NO_ERR != get_error ())
     261            0 :             push_error (ERR_BACKEND_LOCKED, {});
     262            0 :         LEAVE("push error book is already open ");
     263            0 :         return;
     264              :     }
     265              : 
     266              :     /* seriously invalid */
     267           47 :     if (!new_uri)
     268              :     {
     269            0 :         if (ERR_BACKEND_NO_ERR != get_error ())
     270            0 :             push_error (ERR_BACKEND_BAD_URL, {});
     271            0 :         LEAVE("push error missing new_uri");
     272            0 :         return;
     273              :     }
     274              : 
     275           47 :     char * scheme {g_uri_parse_scheme (new_uri)};
     276           47 :     char * filename {nullptr};
     277           47 :     if (g_strcmp0 (scheme, "file") == 0)
     278           40 :         filename = gnc_uri_get_path(new_uri);
     279            7 :     else if (!scheme)
     280            0 :         filename = g_strdup (new_uri);
     281              : 
     282           47 :     if (filename && g_file_test (filename, G_FILE_TEST_IS_DIR))
     283              :     {
     284            0 :         if (ERR_BACKEND_NO_ERR == get_error ())
     285            0 :             push_error (ERR_BACKEND_BAD_URL, {});
     286            0 :         g_free (filename);
     287            0 :         g_free (scheme);
     288            0 :         LEAVE("Can't open a directory");
     289            0 :         return;
     290              :     }
     291              :     /* destroy the old backend */
     292           47 :     destroy_backend ();
     293              :     /* Store the session URL  */
     294           47 :     m_uri = new_uri;
     295           47 :     m_creating = mode == SESSION_NEW_STORE || mode == SESSION_NEW_OVERWRITE;
     296           47 :     if (filename)
     297           80 :         load_backend ("file");
     298              :     else                       /* access method found, load appropriate backend */
     299           14 :         load_backend (scheme);
     300           47 :     g_free (filename);
     301           47 :     g_free (scheme);
     302              : 
     303              :     /* No backend was found. That's bad. */
     304           47 :     if (m_backend == nullptr)
     305              :     {
     306            1 :         m_uri = {};
     307            1 :         if (ERR_BACKEND_NO_ERR == get_error ())
     308            0 :             push_error (ERR_BACKEND_BAD_URL, {});
     309            1 :         LEAVE (" BAD: no backend: sess=%p book-id=%s",
     310              :                this,  new_uri);
     311            1 :         return;
     312              :     }
     313              : 
     314              :     /* If there's a begin method, call that. */
     315           46 :     m_backend->session_begin(this, m_uri.c_str(), mode);
     316           46 :     PINFO ("Done running session_begin on backend");
     317           46 :     QofBackendError const err {m_backend->get_error()};
     318           46 :     auto msg (m_backend->get_message());
     319           46 :     if (err != ERR_BACKEND_NO_ERR)
     320              :     {
     321            2 :         m_uri = {};
     322            2 :         push_error (err, msg);
     323            2 :         LEAVE (" backend error %d %s", err, msg.empty() ? "(null)" : msg.c_str());
     324            2 :         return;
     325              :     }
     326           44 :     if (!msg.empty())
     327              :     {
     328            0 :         PWARN("%s", msg.c_str());
     329              :     }
     330              : 
     331           44 :     LEAVE (" sess=%p book-id=%s", this,  new_uri);
     332           46 : }
     333              : 
     334              : void
     335          263 : QofSessionImpl::end () noexcept
     336              : {
     337          263 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     338          263 :     if (m_backend != nullptr)
     339           74 :         m_backend->session_end();
     340          263 :     clear_error ();
     341          263 :     m_uri.clear();
     342          263 :     LEAVE ("sess=%p uri=%s", this, m_uri.c_str ());
     343          263 : }
     344              : 
     345              : /* error handling functions --------------------------------*/
     346              : 
     347              : void
     348          382 : QofSessionImpl::clear_error () noexcept
     349              : {
     350          382 :     m_last_err = ERR_BACKEND_NO_ERR;
     351          382 :     m_error_message = {};
     352              : 
     353              :     /* pop the stack on the backend as well. */
     354          382 :     if (auto backend = qof_book_get_backend (m_book))
     355              :     {
     356           79 :         QofBackendError err = ERR_BACKEND_NO_ERR;
     357              :         do
     358           79 :             err = backend->get_error();
     359           79 :         while (err != ERR_BACKEND_NO_ERR);
     360              :     }
     361          382 : }
     362              : 
     363              : void
     364           33 : QofSessionImpl::push_error (QofBackendError const err, std::string message) noexcept
     365              : {
     366           33 :     m_last_err = err;
     367           33 :     m_error_message = message;
     368           33 : }
     369              : 
     370              : QofBackendError
     371          149 : QofSessionImpl::get_error () noexcept
     372              : {
     373              :     /* if we have a local error, return that. */
     374          149 :     if (m_last_err != ERR_BACKEND_NO_ERR)
     375            9 :         return m_last_err;
     376          140 :     auto qof_be = qof_book_get_backend (m_book);
     377          140 :     if (qof_be == nullptr) return ERR_BACKEND_NO_ERR;
     378              : 
     379           73 :     m_last_err = qof_be->get_error();
     380           73 :     return m_last_err;
     381              : }
     382              : 
     383              : const std::string&
     384            0 : QofSessionImpl::get_error_message () const noexcept
     385              : {
     386            0 :     return m_error_message;
     387              : }
     388              : 
     389              : QofBackendError
     390            4 : QofSessionImpl::pop_error () noexcept
     391              : {
     392            4 :     QofBackendError err {get_error ()};
     393            4 :     clear_error ();
     394            4 :     return err;
     395              : }
     396              : 
     397              : /* Accessors (getters/setters) -----------------------------*/
     398              : 
     399              : QofBook *
     400        13720 : QofSessionImpl::get_book () const noexcept
     401              : {
     402        13720 :     if (!m_book) return nullptr;
     403        13720 :     if (qof_book_is_open (m_book))
     404        13720 :         return m_book;
     405            0 :     return nullptr;
     406              : }
     407              : 
     408              : QofBackend *
     409            3 : QofSession::get_backend () const noexcept
     410              : {
     411            3 :     return m_backend;
     412              : }
     413              : 
     414              : const std::string&
     415            0 : QofSessionImpl::get_file_path () const noexcept
     416              : {
     417            0 :     auto backend = qof_book_get_backend (m_book);
     418            0 :     if (!backend) return empty_string;
     419            0 :     return backend->get_uri();
     420              : }
     421              : 
     422              : std::string const &
     423            0 : QofSessionImpl::get_uri () const noexcept
     424              : {
     425            0 :     return m_uri;
     426              : }
     427              : 
     428              : bool
     429            0 : QofSessionImpl::is_saving () const noexcept
     430              : {
     431            0 :     return m_saving;
     432              : }
     433              : 
     434              : /* Manipulators (save, load, etc.) -------------------------*/
     435              : 
     436              : void
     437           16 : QofSessionImpl::save (QofPercentageFunc percentage_func) noexcept
     438              : {
     439           16 :     if (!qof_book_session_not_saved (m_book)) //Clean book, nothing to do.
     440            7 :         return;
     441            9 :     m_saving = true;
     442            9 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     443              : 
     444              :     /* If there is a backend, the book is dirty, and the backend is reachable
     445              :      * (i.e. we can communicate with it), then synchronize with the backend.  If
     446              :      * we cannot contact the backend (e.g.  because we've gone offline, the
     447              :      * network has crashed, etc.)  then raise an error so that the controlling
     448              :      * dialog can offer the user a chance to save in a different way.
     449              :      */
     450            9 :     if (m_backend)
     451              :     {
     452              :         /* if invoked as SaveAs(), then backend not yet set */
     453            9 :         if (qof_book_get_backend (m_book) != m_backend)
     454            9 :             qof_book_set_backend (m_book, m_backend);
     455            9 :         m_backend->set_percentage(percentage_func);
     456            9 :         m_backend->sync(m_book);
     457            9 :         auto err = m_backend->get_error();
     458            9 :         if (err != ERR_BACKEND_NO_ERR)
     459              :         {
     460            0 :             push_error (err, {});
     461            0 :             m_saving = false;
     462            0 :             return;
     463              :         }
     464              :         /* If we got to here, then the backend saved everything
     465              :         * just fine, and we are done. So return. */
     466            9 :         clear_error ();
     467            9 :         LEAVE("Success");
     468              :     }
     469              :     else
     470              :     {
     471            0 :         push_error (ERR_BACKEND_NO_HANDLER, "failed to load backend");
     472            0 :         LEAVE("error -- No backend!");
     473              :     }
     474            9 :     m_saving = false;
     475              : }
     476              : 
     477              : void
     478            1 : QofSessionImpl::safe_save (QofPercentageFunc percentage_func) noexcept
     479              : {
     480            1 :     if (!(m_backend && m_book)) return;
     481            1 :     if (qof_book_get_backend (m_book) != m_backend)
     482            0 :         qof_book_set_backend (m_book, m_backend);
     483            1 :     m_backend->set_percentage(percentage_func);
     484            1 :     m_backend->safe_sync(get_book ());
     485            1 :     auto err = m_backend->get_error();
     486            1 :     auto msg = m_backend->get_message();
     487            1 :     if (err != ERR_BACKEND_NO_ERR)
     488              :     {
     489            0 :         m_uri = "";
     490            0 :         push_error (err, msg);
     491              :     }
     492            1 : }
     493              : 
     494              : void
     495            1 : QofSessionImpl::ensure_all_data_loaded () noexcept
     496              : {
     497            1 :     if (!(m_backend && m_book)) return;
     498            1 :     if (qof_book_get_backend (m_book) != m_backend)
     499            0 :         qof_book_set_backend (m_book, m_backend);
     500            1 :     m_backend->load(m_book, LOAD_TYPE_LOAD_ALL);
     501            1 :     push_error (m_backend->get_error(), {});
     502              : }
     503              : 
     504              : void
     505            9 : QofSessionImpl::swap_books (QofSessionImpl & other) noexcept
     506              : {
     507            9 :     ENTER ("sess1=%p sess2=%p", this, &other);
     508              :     // don't swap (that is, double-swap) read_only flags
     509            9 :     if (m_book && other.m_book)
     510            4 :         qof_book_swap_books_readonly (m_book, other.m_book);
     511            9 :     std::swap (m_book, other.m_book);
     512            9 :     auto mybackend = qof_book_get_backend (m_book);
     513            9 :     qof_book_set_backend (m_book, qof_book_get_backend (other.m_book));
     514            9 :     qof_book_set_backend (other.m_book, mybackend);
     515            9 :     LEAVE (" ");
     516            9 : }
     517              : 
     518              : bool
     519            0 : QofSessionImpl::events_pending () const noexcept
     520              : {
     521            0 :     return false;
     522              : }
     523              : 
     524              : bool
     525            0 : QofSessionImpl::process_events () const noexcept
     526              : {
     527            0 :     return false;
     528              : }
     529              : 
     530              : /* XXX This exports the list of accounts to a file.  It does not
     531              :  * export any transactions.  It's a place-holder until full
     532              :  * book-closing is implemented.
     533              :  */
     534              : bool
     535            0 : QofSessionImpl::export_session (QofSessionImpl & real_session,
     536              :                                 QofPercentageFunc percentage_func) noexcept
     537              : {
     538            0 :     auto real_book = real_session.get_book ();
     539            0 :     ENTER ("tmp_session=%p real_session=%p book=%p uri=%s",
     540              :            this, &real_session, real_book, m_uri.c_str ());
     541              : 
     542              :     /* There must be a backend or else.  (It should always be the file
     543              :      * backend too.)
     544              :      */
     545            0 :     if (!m_backend) return false;
     546              : 
     547            0 :     m_backend->set_percentage(percentage_func);
     548              : 
     549            0 :     m_backend->export_coa(real_book);
     550            0 :     auto err = m_backend->get_error();
     551            0 :     if (err != ERR_BACKEND_NO_ERR)
     552            0 :         return false;
     553            0 :     return true;
     554              : }
     555              : 
     556              : /* C Wrapper Functions */
     557              : /* ====================================================================== */
     558              : 
     559              : const char *
     560            0 : qof_session_get_error_message (const QofSession * session)
     561              : {
     562            0 :     if (!session) return "";
     563            0 :     return session->get_error_message ().c_str ();
     564              : }
     565              : 
     566              : QofBackendError
     567            4 : qof_session_pop_error (QofSession * session)
     568              : {
     569            4 :     if (!session) return ERR_BACKEND_NO_BACKEND;
     570            4 :     return session->pop_error ();
     571              : }
     572              : 
     573              : QofBook *
     574        13719 : qof_session_get_book (const QofSession *session)
     575              : {
     576        13719 :     if (!session) return NULL;
     577        13719 :     return session->get_book ();
     578              : }
     579              : 
     580              : const char *
     581            0 : qof_session_get_file_path (const QofSession *session)
     582              : {
     583            0 :     if (!session) return nullptr;
     584            0 :     auto& path{session->get_file_path()};
     585            0 :     return path.empty() ? nullptr : path.c_str ();
     586              : }
     587              : 
     588              : void
     589            1 : qof_session_ensure_all_data_loaded (QofSession *session)
     590              : {
     591            1 :     if (session == nullptr) return;
     592            1 :     return session->ensure_all_data_loaded ();
     593              : }
     594              : 
     595              : const char *
     596            0 : qof_session_get_url (const QofSession *session)
     597              : {
     598            0 :     if (!session) return NULL;
     599            0 :     return session->get_uri ().c_str ();
     600              : }
     601              : 
     602              : QofBackend *
     603            3 : qof_session_get_backend (const QofSession *session)
     604              : {
     605            3 :     if (!session) return NULL;
     606            3 :     return session->get_backend ();
     607              : }
     608              : 
     609              : void
     610           47 : qof_session_begin (QofSession *session, const char * uri, SessionOpenMode mode)
     611              : {
     612           47 :     if (!session) return;
     613           47 :     session->begin(uri, mode);
     614              : }
     615              : 
     616              : void
     617           30 : qof_session_load (QofSession *session,
     618              :                   QofPercentageFunc percentage_func)
     619              : {
     620           30 :     if (!session) return;
     621           30 :     session->load (percentage_func);
     622              : }
     623              : 
     624              : void
     625           16 : qof_session_save (QofSession *session,
     626              :                   QofPercentageFunc percentage_func)
     627              : {
     628           16 :     if (!session) return;
     629           16 :     session->save (percentage_func);
     630              : }
     631              : 
     632              : void
     633            1 : qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
     634              : {
     635            1 :     if (!session) return;
     636            1 :     session->safe_save (percentage_func);
     637              : }
     638              : 
     639              : gboolean
     640            0 : qof_session_save_in_progress(const QofSession *session)
     641              : {
     642            0 :     if (!session) return false;
     643            0 :     return session->is_saving ();
     644              : }
     645              : 
     646              : void
     647           98 : qof_session_end (QofSession *session)
     648              : {
     649           98 :     if (!session) return;
     650           98 :     session->end ();
     651              : }
     652              : 
     653              : void
     654            9 : qof_session_swap_data (QofSession *session_1, QofSession *session_2)
     655              : {
     656            9 :     if (session_1 == session_2) return;
     657            9 :     if (!session_1 || !session_2) return;
     658            9 :     session_1->swap_books (*session_2);
     659              : }
     660              : 
     661              : gboolean
     662            0 : qof_session_events_pending (const QofSession *session)
     663              : {
     664            0 :     if (!session) return false;
     665            0 :     return session->events_pending ();
     666              : }
     667              : 
     668              : gboolean
     669            0 : qof_session_process_events (QofSession *session)
     670              : {
     671            0 :     if (!session) return FALSE;
     672            0 :     return session->process_events ();
     673              : }
     674              : 
     675              : gboolean
     676            0 : qof_session_export (QofSession *tmp_session,
     677              :                     QofSession *real_session,
     678              :                     QofPercentageFunc percentage_func)
     679              : {
     680            0 :     if ((!tmp_session) || (!real_session)) return FALSE;
     681            0 :     return tmp_session->export_session (*real_session, percentage_func);
     682              : }
     683              : 
     684              : /* ================= Static function access for testing ================= */
     685              : 
     686              : void init_static_qofsession_pointers (void);
     687              : 
     688            0 : void qof_session_load_backend (QofSession * session, const char * access_method)
     689              : {
     690            0 :     session->load_backend (access_method);
     691            0 : }
     692              : 
     693              : static void
     694            0 : qof_session_clear_error (QofSession * session)
     695              : {
     696            0 :     session->clear_error ();
     697            0 : }
     698              : 
     699              : static void
     700            0 : qof_session_destroy_backend (QofSession * session)
     701              : {
     702            0 :     session->destroy_backend ();
     703            0 : }
     704              : 
     705            0 : void qof_session_set_uri (QofSession * session, char const * uri)
     706              : {
     707            0 :     if (!uri)
     708            0 :         session->m_uri = "";
     709              :     else
     710            0 :         session->m_uri = uri;
     711            0 : }
     712              : 
     713              : void (*p_qof_session_load_backend) (QofSession *, const char * access_method);
     714              : void (*p_qof_session_clear_error) (QofSession *);
     715              : void (*p_qof_session_destroy_backend) (QofSession *);
     716              : void (*p_qof_session_set_uri) (QofSession *, char const * uri);
     717              : 
     718              : void
     719            0 : init_static_qofsession_pointers (void)
     720              : {
     721            0 :     p_qof_session_load_backend = &qof_session_load_backend;
     722            0 :     p_qof_session_clear_error = &qof_session_clear_error;
     723            0 :     p_qof_session_destroy_backend = &qof_session_destroy_backend;
     724            0 :     p_qof_session_set_uri = &qof_session_set_uri;
     725            0 : }
     726              : 
     727              : QofBackendError
     728          115 : qof_session_get_error (QofSession * session)
     729              : {
     730          115 :     if (!session) return ERR_BACKEND_NO_BACKEND;
     731          115 :     return session->get_error();
     732              : }
        

Generated by: LCOV version 2.0-1