LCOV - code coverage report
Current view: top level - libgnucash/engine - qofsession.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 67.1 % 328 220
Test Date: 2025-02-07 16:25:45 Functions: 58.2 % 55 32
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     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.h"
      55                 :             : #include "qof-backend.hpp"
      56                 :             : #include "qofsession.hpp"
      57                 :             : #include "gnc-backend-prov.hpp"
      58                 :             : 
      59                 :             : #include <vector>
      60                 :             : #include <boost/algorithm/string.hpp>
      61                 :             : #include <vector>
      62                 :             : #include <algorithm>
      63                 :             : #include <string>
      64                 :             : #include <sstream>
      65                 :             : 
      66                 :             : using ProviderVec =  std::vector<QofBackendProvider_ptr>;
      67                 :             : static ProviderVec s_providers;
      68                 :             : static const std::string empty_string{};
      69                 :             : /*
      70                 :             :  * These getters are used in tests to reach static vars from outside
      71                 :             :  * They should be removed when no longer needed
      72                 :             :  */
      73                 :             : 
      74                 :             : ProviderVec& get_providers (void );
      75                 :             : bool get_providers_initialized (void );
      76                 :             : 
      77                 :             : ProviderVec&
      78                 :           0 : get_providers (void)
      79                 :             : {
      80                 :           0 :     return s_providers;
      81                 :             : }
      82                 :             : 
      83                 :             : bool
      84                 :           0 : get_providers_initialized (void)
      85                 :             : {
      86                 :           0 :     return !s_providers.empty();
      87                 :             : }
      88                 :             : 
      89                 :             : void
      90                 :         244 : qof_backend_register_provider (QofBackendProvider_ptr&& prov)
      91                 :             : {
      92                 :         244 :     s_providers.emplace_back(std::move(prov));
      93                 :         244 : }
      94                 :             : 
      95                 :             : void
      96                 :           0 : qof_backend_unregister_all_providers ()
      97                 :             : {
      98                 :           0 :     s_providers.clear ();
      99                 :           0 : }
     100                 :             : 
     101                 :             : /* Called from C so we have to keep the GList for now. */
     102                 :             : GList*
     103                 :           6 : qof_backend_get_registered_access_method_list(void)
     104                 :             : {
     105                 :           6 :     GList* list = NULL;
     106                 :           6 :     std::for_each(s_providers.begin(), s_providers.end(),
     107                 :           0 :                   [&list](QofBackendProvider_ptr& provider) {
     108                 :           0 :                       gpointer method = reinterpret_cast<gpointer>(const_cast<char*>(provider->access_method));
     109                 :           0 :                       list = g_list_prepend(list, method);
     110                 :           0 :                   });
     111                 :           6 :     return list;
     112                 :             : }
     113                 :             : 
     114                 :             : /* QofSessionImpl */
     115                 :             : /* ====================================================================== */
     116                 :             : /* Constructor/Destructor ----------------------------------*/
     117                 :             : 
     118                 :         241 : QofSessionImpl::QofSessionImpl (QofBook* book) noexcept
     119                 :         241 :   : m_backend {},
     120                 :         241 :     m_book {book},
     121                 :         241 :     m_uri {},
     122                 :         241 :     m_saving {false},
     123                 :         241 :     m_last_err {},
     124                 :         241 :     m_error_message {}
     125                 :             : {
     126                 :         241 : }
     127                 :             : 
     128                 :         139 : QofSessionImpl::~QofSessionImpl () noexcept
     129                 :             : {
     130                 :         139 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     131                 :         139 :     end ();
     132                 :         139 :     destroy_backend ();
     133                 :         139 :     qof_book_set_backend (m_book, nullptr);
     134                 :         139 :     qof_book_destroy (m_book);
     135                 :         139 :     m_book = nullptr;
     136                 :         139 :     LEAVE ("sess=%p", this);
     137                 :         139 : }
     138                 :             : 
     139                 :             : void
     140                 :         139 : qof_session_destroy (QofSession * session)
     141                 :             : {
     142                 :         139 :     delete session;
     143                 :         139 : }
     144                 :             : 
     145                 :             : QofSession *
     146                 :         241 : qof_session_new (QofBook* book)
     147                 :             : {
     148                 :         241 :     return new QofSessionImpl(book);
     149                 :             : }
     150                 :             : 
     151                 :             : void
     152                 :         179 : QofSessionImpl::destroy_backend () noexcept
     153                 :             : {
     154                 :         179 :     if (m_backend)
     155                 :             :     {
     156                 :          18 :         clear_error ();
     157                 :          18 :         delete m_backend;
     158                 :          18 :         m_backend = nullptr;
     159                 :          18 :         qof_book_set_backend (m_book, nullptr);
     160                 :             :     }
     161                 :         179 : }
     162                 :             : 
     163                 :             : /* ====================================================================== */
     164                 :             : 
     165                 :             : void
     166                 :          40 : QofSessionImpl::load_backend (std::string access_method) noexcept
     167                 :             : {
     168                 :          40 :     std::ostringstream s;
     169                 :          40 :     s << " list=" << s_providers.size();
     170                 :          40 :     ENTER ("%s", s.str().c_str());
     171                 :          81 :     for (auto const & prov : s_providers)
     172                 :             :     {
     173                 :          80 :         if (!boost::iequals (access_method, prov->access_method))
     174                 :             :         {
     175                 :          38 :             PINFO ("The provider providers access_method, %s, but we're loading for access_method, %s. Skipping.",
     176                 :             :                     prov->access_method, access_method.c_str ());
     177                 :          38 :             continue;
     178                 :             :         }
     179                 :          42 :         PINFO (" Selected provider %s", prov->provider_name);
     180                 :             :         // Only do a type check when trying to open an existing file
     181                 :             :         // When saving over an existing file the contents of the original file don't matter
     182                 :          42 :         if (!m_creating && !prov->type_check (m_uri.c_str ()))
     183                 :             :         {
     184                 :           3 :             PINFO("Provider, %s, reported not being usable for book, %s.",
     185                 :             :                     prov->provider_name, m_uri.c_str ());
     186                 :           3 :             continue;
     187                 :             :         }
     188                 :          39 :         m_backend = prov->create_backend();
     189                 :          39 :         LEAVE (" ");
     190                 :          39 :         return;
     191                 :             :     }
     192                 :           1 :     std::string msg {"failed to get_backend using access method \"" + access_method + "\""};
     193                 :           1 :     push_error (ERR_BACKEND_NO_HANDLER, msg);
     194                 :           1 :     LEAVE (" ");
     195                 :          40 : }
     196                 :             : 
     197                 :             : void
     198                 :          27 : QofSessionImpl::load (QofPercentageFunc percentage_func) noexcept
     199                 :             : {
     200                 :             :     /* We must have an empty book to load into or bad things will happen. */
     201                 :          27 :     g_return_if_fail(m_book && qof_book_empty(m_book));
     202                 :             : 
     203                 :          26 :     if (!m_uri.size ()) return;
     204                 :          26 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     205                 :             : 
     206                 :             :     /* At this point, we should are supposed to have a valid book
     207                 :             :      * id and a lock on the file. */
     208                 :          26 :     clear_error ();
     209                 :             : 
     210                 :             :     /* This code should be sufficient to initialize *any* backend,
     211                 :             :      * whether http, postgres, or anything else that might come along.
     212                 :             :      * Basically, the idea is that by now, a backend has already been
     213                 :             :      * created & set up.  At this point, we only need to get the
     214                 :             :      * top-level account group out of the backend, and that is a
     215                 :             :      * generic, backend-independent operation.
     216                 :             :      */
     217                 :          26 :     qof_book_set_backend (m_book, m_backend);
     218                 :             : 
     219                 :             :     /* Starting the session should result in a bunch of accounts
     220                 :             :      * and currencies being downloaded, but probably no transactions;
     221                 :             :      * The GUI will need to do a query for that.
     222                 :             :      */
     223                 :          26 :     if (m_backend)
     224                 :             :     {
     225                 :          26 :         m_backend->set_percentage(percentage_func);
     226                 :          26 :         m_backend->load (m_book, LOAD_TYPE_INITIAL_LOAD);
     227                 :          26 :         push_error (m_backend->get_error(), {});
     228                 :             :     }
     229                 :             : 
     230                 :          26 :     auto err = get_error ();
     231                 :          26 :     if ((err != ERR_BACKEND_NO_ERR) &&
     232                 :           2 :         (err != ERR_FILEIO_FILE_TOO_OLD) &&
     233                 :           2 :         (err != ERR_FILEIO_NO_ENCODING) &&
     234                 :           2 :         (err != ERR_FILEIO_FILE_UPGRADE) &&
     235                 :           1 :         (err != ERR_SQL_DB_TOO_OLD) &&
     236                 :             :         (err != ERR_SQL_DB_TOO_NEW))
     237                 :             :     {
     238                 :             :         // Something failed, delete and restore new ones.
     239                 :           0 :         destroy_backend();
     240                 :           0 :         qof_book_destroy (m_book);
     241                 :           0 :         m_book = qof_book_new();
     242                 :           0 :         LEAVE ("error from backend %d", get_error ());
     243                 :           0 :         return;
     244                 :             :     }
     245                 :             : 
     246                 :          26 :     LEAVE ("sess = %p, uri=%s", this, m_uri.c_str ());
     247                 :             : }
     248                 :             : 
     249                 :             : void
     250                 :          40 : QofSessionImpl::begin (const char* new_uri, SessionOpenMode mode) noexcept
     251                 :             : {
     252                 :             : 
     253                 :             : 
     254                 :          40 :     ENTER (" sess=%p mode=%d, URI=%s", this, mode, new_uri);
     255                 :          40 :     clear_error ();
     256                 :             :     /* Check to see if this session is already open */
     257                 :          40 :     if (m_uri.size ())
     258                 :             :     {
     259                 :           0 :         if (ERR_BACKEND_NO_ERR != get_error ())
     260                 :           0 :             push_error (ERR_BACKEND_LOCKED, {});
     261                 :           0 :         LEAVE("push error book is already open ");
     262                 :           0 :         return;
     263                 :             :     }
     264                 :             : 
     265                 :             :     /* seriously invalid */
     266                 :          40 :     if (!new_uri)
     267                 :             :     {
     268                 :           0 :         if (ERR_BACKEND_NO_ERR != get_error ())
     269                 :           0 :             push_error (ERR_BACKEND_BAD_URL, {});
     270                 :           0 :         LEAVE("push error missing new_uri");
     271                 :           0 :         return;
     272                 :             :     }
     273                 :             : 
     274                 :          40 :     char * scheme {g_uri_parse_scheme (new_uri)};
     275                 :          40 :     char * filename {nullptr};
     276                 :          40 :     if (g_strcmp0 (scheme, "file") == 0)
     277                 :           2 :         filename = g_filename_from_uri (new_uri, nullptr, nullptr);
     278                 :          38 :     else if (!scheme)
     279                 :          32 :         filename = g_strdup (new_uri);
     280                 :             : 
     281                 :          40 :     if (filename && g_file_test (filename, G_FILE_TEST_IS_DIR))
     282                 :             :     {
     283                 :           0 :         if (ERR_BACKEND_NO_ERR == get_error ())
     284                 :           0 :             push_error (ERR_BACKEND_BAD_URL, {});
     285                 :           0 :         g_free (filename);
     286                 :           0 :         g_free (scheme);
     287                 :           0 :         LEAVE("Can't open a directory");
     288                 :           0 :         return;
     289                 :             :     }
     290                 :             :     /* destroy the old backend */
     291                 :          40 :     destroy_backend ();
     292                 :             :     /* Store the session URL  */
     293                 :          40 :     m_uri = new_uri;
     294                 :          40 :     m_creating = mode == SESSION_NEW_STORE || mode == SESSION_NEW_OVERWRITE;
     295                 :          40 :     if (filename)
     296                 :          68 :         load_backend ("file");
     297                 :             :     else                       /* access method found, load appropriate backend */
     298                 :          12 :         load_backend (scheme);
     299                 :          40 :     g_free (filename);
     300                 :          40 :     g_free (scheme);
     301                 :             : 
     302                 :             :     /* No backend was found. That's bad. */
     303                 :          40 :     if (m_backend == nullptr)
     304                 :             :     {
     305                 :           1 :         m_uri = {};
     306                 :           1 :         if (ERR_BACKEND_NO_ERR == get_error ())
     307                 :           0 :             push_error (ERR_BACKEND_BAD_URL, {});
     308                 :           1 :         LEAVE (" BAD: no backend: sess=%p book-id=%s",
     309                 :             :                this,  new_uri);
     310                 :           1 :         return;
     311                 :             :     }
     312                 :             : 
     313                 :             :     /* If there's a begin method, call that. */
     314                 :          39 :     m_backend->session_begin(this, m_uri.c_str(), mode);
     315                 :          39 :     PINFO ("Done running session_begin on backend");
     316                 :          39 :     QofBackendError const err {m_backend->get_error()};
     317                 :          39 :     auto msg (m_backend->get_message());
     318                 :          39 :     if (err != ERR_BACKEND_NO_ERR)
     319                 :             :     {
     320                 :           2 :         m_uri = {};
     321                 :           2 :         push_error (err, msg);
     322                 :           2 :         LEAVE (" backend error %d %s", err, msg.empty() ? "(null)" : msg.c_str());
     323                 :           2 :         return;
     324                 :             :     }
     325                 :          37 :     if (!msg.empty())
     326                 :             :     {
     327                 :           0 :         PWARN("%s", msg.c_str());
     328                 :             :     }
     329                 :             : 
     330                 :          37 :     LEAVE (" sess=%p book-id=%s", this,  new_uri);
     331                 :          39 : }
     332                 :             : 
     333                 :             : void
     334                 :         204 : QofSessionImpl::end () noexcept
     335                 :             : {
     336                 :         204 :     ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
     337                 :         204 :     auto backend = qof_book_get_backend (m_book);
     338                 :         204 :     if (backend != nullptr)
     339                 :          42 :         backend->session_end();
     340                 :         204 :     clear_error ();
     341                 :         204 :     m_uri.clear();
     342                 :         204 :     LEAVE ("sess=%p uri=%s", this, m_uri.c_str ());
     343                 :         204 : }
     344                 :             : 
     345                 :             : /* error handling functions --------------------------------*/
     346                 :             : 
     347                 :             : void
     348                 :         300 : QofSessionImpl::clear_error () noexcept
     349                 :             : {
     350                 :         300 :     m_last_err = ERR_BACKEND_NO_ERR;
     351                 :         300 :     m_error_message = {};
     352                 :             : 
     353                 :             :     /* pop the stack on the backend as well. */
     354                 :         300 :     if (auto backend = qof_book_get_backend (m_book))
     355                 :             :     {
     356                 :          66 :         QofBackendError err = ERR_BACKEND_NO_ERR;
     357                 :             :         do
     358                 :          66 :             err = backend->get_error();
     359                 :          66 :         while (err != ERR_BACKEND_NO_ERR);
     360                 :             :     }
     361                 :         300 : }
     362                 :             : 
     363                 :             : void
     364                 :          30 : QofSessionImpl::push_error (QofBackendError const err, std::string message) noexcept
     365                 :             : {
     366                 :          30 :     m_last_err = err;
     367                 :          30 :     m_error_message = message;
     368                 :          30 : }
     369                 :             : 
     370                 :             : QofBackendError
     371                 :         109 : QofSessionImpl::get_error () noexcept
     372                 :             : {
     373                 :             :     /* if we have a local error, return that. */
     374                 :         109 :     if (m_last_err != ERR_BACKEND_NO_ERR)
     375                 :           9 :         return m_last_err;
     376                 :         100 :     auto qof_be = qof_book_get_backend (m_book);
     377                 :         100 :     if (qof_be == nullptr) return ERR_BACKEND_NO_ERR;
     378                 :             : 
     379                 :          65 :     m_last_err = qof_be->get_error();
     380                 :          65 :     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                 :       41638 : QofSessionImpl::get_book () const noexcept
     401                 :             : {
     402                 :       41638 :     if (!m_book) return nullptr;
     403                 :       41638 :     if ('y' == m_book->book_open)
     404                 :       41638 :         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                 :          14 : QofSessionImpl::save (QofPercentageFunc percentage_func) noexcept
     438                 :             : {
     439                 :          14 :     if (!qof_book_session_not_saved (m_book)) //Clean book, nothing to do.
     440                 :           6 :         return;
     441                 :           8 :     m_saving = true;
     442                 :           8 :     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                 :           8 :     if (m_backend)
     451                 :             :     {
     452                 :             :         /* if invoked as SaveAs(), then backend not yet set */
     453                 :           8 :         if (qof_book_get_backend (m_book) != m_backend)
     454                 :           8 :             qof_book_set_backend (m_book, m_backend);
     455                 :           8 :         m_backend->set_percentage(percentage_func);
     456                 :           8 :         m_backend->sync(m_book);
     457                 :           8 :         auto err = m_backend->get_error();
     458                 :           8 :         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                 :           8 :         clear_error ();
     467                 :           8 :         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                 :           8 :     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                 :           8 : QofSessionImpl::swap_books (QofSessionImpl & other) noexcept
     506                 :             : {
     507                 :           8 :     ENTER ("sess1=%p sess2=%p", this, &other);
     508                 :             :     // don't swap (that is, double-swap) read_only flags
     509                 :           8 :     if (m_book && other.m_book)
     510                 :           3 :         std::swap (m_book->read_only, other.m_book->read_only);
     511                 :           8 :     std::swap (m_book, other.m_book);
     512                 :           8 :     auto mybackend = qof_book_get_backend (m_book);
     513                 :           8 :     qof_book_set_backend (m_book, qof_book_get_backend (other.m_book));
     514                 :           8 :     qof_book_set_backend (other.m_book, mybackend);
     515                 :           8 :     LEAVE (" ");
     516                 :           8 : }
     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                 :       41637 : qof_session_get_book (const QofSession *session)
     575                 :             : {
     576                 :       41637 :     if (!session) return NULL;
     577                 :       41637 :     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                 :          40 : qof_session_begin (QofSession *session, const char * uri, SessionOpenMode mode)
     611                 :             : {
     612                 :          40 :     if (!session) return;
     613                 :          40 :     session->begin(uri, mode);
     614                 :             : }
     615                 :             : 
     616                 :             : void
     617                 :          27 : qof_session_load (QofSession *session,
     618                 :             :                   QofPercentageFunc percentage_func)
     619                 :             : {
     620                 :          27 :     if (!session) return;
     621                 :          27 :     session->load (percentage_func);
     622                 :             : }
     623                 :             : 
     624                 :             : void
     625                 :          14 : qof_session_save (QofSession *session,
     626                 :             :                   QofPercentageFunc percentage_func)
     627                 :             : {
     628                 :          14 :     if (!session) return;
     629                 :          14 :     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                 :          65 : qof_session_end (QofSession *session)
     648                 :             : {
     649                 :          65 :     if (!session) return;
     650                 :          65 :     session->end ();
     651                 :             : }
     652                 :             : 
     653                 :             : void
     654                 :           8 : qof_session_swap_data (QofSession *session_1, QofSession *session_2)
     655                 :             : {
     656                 :           8 :     if (session_1 == session_2) return;
     657                 :           8 :     if (!session_1 || !session_2) return;
     658                 :           8 :     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                 :          78 : qof_session_get_error (QofSession * session)
     729                 :             : {
     730                 :          78 :     if (!session) return ERR_BACKEND_NO_BACKEND;
     731                 :          78 :     return session->get_error();
     732                 :             : }
        

Generated by: LCOV version 2.0-1