GnuCash  5.6-150-g038405b370+
qofsession.cpp
Go to the documentation of this file.
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 
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 get_providers (void)
80 {
81  return s_providers;
82 }
83 
84 bool
85 get_providers_initialized (void)
86 {
87  return !s_providers.empty();
88 }
89 
90 void
91 qof_backend_register_provider (QofBackendProvider_ptr&& prov)
92 {
93  s_providers.emplace_back(std::move(prov));
94 }
95 
96 void
97 qof_backend_unregister_all_providers ()
98 {
99  s_providers.clear ();
100 }
101 
102 /* Called from C so we have to keep the GList for now. */
103 GList*
105 {
106  GList* list = NULL;
107  std::for_each(s_providers.begin(), s_providers.end(),
108  [&list](QofBackendProvider_ptr& provider) {
109  gpointer method = reinterpret_cast<gpointer>(const_cast<char*>(provider->access_method));
110  list = g_list_prepend(list, method);
111  });
112  return list;
113 }
114 
115 /* QofSessionImpl */
116 /* ====================================================================== */
117 /* Constructor/Destructor ----------------------------------*/
118 
119 QofSessionImpl::QofSessionImpl (QofBook* book) noexcept
120  : m_backend {},
121  m_book {book},
122  m_uri {},
123  m_saving {false},
124  m_last_err {},
125  m_error_message {}
126 {
127 }
128 
129 QofSessionImpl::~QofSessionImpl () noexcept
130 {
131  ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
132  end ();
133  destroy_backend ();
134  qof_book_set_backend (m_book, nullptr);
135  qof_book_destroy (m_book);
136  m_book = nullptr;
137  LEAVE ("sess=%p", this);
138 }
139 
140 void
141 qof_session_destroy (QofSession * session)
142 {
143  delete session;
144 }
145 
146 QofSession *
147 qof_session_new (QofBook* book)
148 {
149  return new QofSessionImpl(book);
150 }
151 
152 void
153 QofSessionImpl::destroy_backend () noexcept
154 {
155  if (m_backend)
156  {
157  clear_error ();
158  delete m_backend;
159  m_backend = nullptr;
160  qof_book_set_backend (m_book, nullptr);
161  }
162 }
163 
164 /* ====================================================================== */
165 
166 void
167 QofSessionImpl::load_backend (std::string access_method) noexcept
168 {
169  std::ostringstream s;
170  s << " list=" << s_providers.size();
171  ENTER ("%s", s.str().c_str());
172  for (auto const & prov : s_providers)
173  {
174  if (!boost::iequals (access_method, prov->access_method))
175  {
176  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  continue;
179  }
180  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  if (!m_creating && !prov->type_check (m_uri.c_str ()))
184  {
185  PINFO("Provider, %s, reported not being usable for book, %s.",
186  prov->provider_name, m_uri.c_str ());
187  continue;
188  }
189  m_backend = prov->create_backend();
190  LEAVE (" ");
191  return;
192  }
193  std::string msg {"failed to get_backend using access method \"" + access_method + "\""};
194  push_error (ERR_BACKEND_NO_HANDLER, msg);
195  LEAVE (" ");
196 }
197 
198 void
199 QofSessionImpl::load (QofPercentageFunc percentage_func) noexcept
200 {
201  /* We must have an empty book to load into or bad things will happen. */
202  g_return_if_fail(m_book && qof_book_empty(m_book));
203 
204  if (!m_uri.size ()) return;
205  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  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  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  if (m_backend)
225  {
226  m_backend->set_percentage(percentage_func);
227  m_backend->load (m_book, LOAD_TYPE_INITIAL_LOAD);
228  push_error (m_backend->get_error(), {});
229  }
230 
231  auto err = get_error ();
232  if ((err != ERR_BACKEND_NO_ERR) &&
233  (err != ERR_FILEIO_FILE_TOO_OLD) &&
234  (err != ERR_FILEIO_NO_ENCODING) &&
235  (err != ERR_FILEIO_FILE_UPGRADE) &&
236  (err != ERR_SQL_DB_TOO_OLD) &&
237  (err != ERR_SQL_DB_TOO_NEW))
238  {
239  // Something failed, delete and restore new ones.
240  destroy_backend();
241  qof_book_destroy (m_book);
242  m_book = qof_book_new();
243  LEAVE ("error from backend %d", get_error ());
244  return;
245  }
246 
247  LEAVE ("sess = %p, uri=%s", this, m_uri.c_str ());
248 }
249 
250 void
251 QofSessionImpl::begin (const char* new_uri, SessionOpenMode mode) noexcept
252 {
253 
254 
255  ENTER (" sess=%p mode=%d, URI=%s", this, mode, new_uri);
256  clear_error ();
257  /* Check to see if this session is already open */
258  if (m_uri.size ())
259  {
260  if (ERR_BACKEND_NO_ERR != get_error ())
261  push_error (ERR_BACKEND_LOCKED, {});
262  LEAVE("push error book is already open ");
263  return;
264  }
265 
266  /* seriously invalid */
267  if (!new_uri)
268  {
269  if (ERR_BACKEND_NO_ERR != get_error ())
270  push_error (ERR_BACKEND_BAD_URL, {});
271  LEAVE("push error missing new_uri");
272  return;
273  }
274 
275  char * scheme {g_uri_parse_scheme (new_uri)};
276  char * filename {nullptr};
277  if (g_strcmp0 (scheme, "file") == 0)
278  filename = gnc_uri_get_path(new_uri);
279  else if (!scheme)
280  filename = g_strdup (new_uri);
281 
282  if (filename && g_file_test (filename, G_FILE_TEST_IS_DIR))
283  {
284  if (ERR_BACKEND_NO_ERR == get_error ())
285  push_error (ERR_BACKEND_BAD_URL, {});
286  g_free (filename);
287  g_free (scheme);
288  LEAVE("Can't open a directory");
289  return;
290  }
291  /* destroy the old backend */
292  destroy_backend ();
293  /* Store the session URL */
294  m_uri = new_uri;
295  m_creating = mode == SESSION_NEW_STORE || mode == SESSION_NEW_OVERWRITE;
296  if (filename)
297  load_backend ("file");
298  else /* access method found, load appropriate backend */
299  load_backend (scheme);
300  g_free (filename);
301  g_free (scheme);
302 
303  /* No backend was found. That's bad. */
304  if (m_backend == nullptr)
305  {
306  m_uri = {};
307  if (ERR_BACKEND_NO_ERR == get_error ())
308  push_error (ERR_BACKEND_BAD_URL, {});
309  LEAVE (" BAD: no backend: sess=%p book-id=%s",
310  this, new_uri);
311  return;
312  }
313 
314  /* If there's a begin method, call that. */
315  m_backend->session_begin(this, m_uri.c_str(), mode);
316  PINFO ("Done running session_begin on backend");
317  QofBackendError const err {m_backend->get_error()};
318  auto msg (m_backend->get_message());
319  if (err != ERR_BACKEND_NO_ERR)
320  {
321  m_uri = {};
322  push_error (err, msg);
323  LEAVE (" backend error %d %s", err, msg.empty() ? "(null)" : msg.c_str());
324  return;
325  }
326  if (!msg.empty())
327  {
328  PWARN("%s", msg.c_str());
329  }
330 
331  LEAVE (" sess=%p book-id=%s", this, new_uri);
332 }
333 
334 void
336 {
337  ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
338  if (m_backend != nullptr)
339  m_backend->session_end();
340  clear_error ();
341  m_uri.clear();
342  LEAVE ("sess=%p uri=%s", this, m_uri.c_str ());
343 }
344 
345 /* error handling functions --------------------------------*/
346 
347 void
348 QofSessionImpl::clear_error () noexcept
349 {
350  m_last_err = ERR_BACKEND_NO_ERR;
351  m_error_message = {};
352 
353  /* pop the stack on the backend as well. */
354  if (auto backend = qof_book_get_backend (m_book))
355  {
356  QofBackendError err = ERR_BACKEND_NO_ERR;
357  do
358  err = backend->get_error();
359  while (err != ERR_BACKEND_NO_ERR);
360  }
361 }
362 
363 void
364 QofSessionImpl::push_error (QofBackendError const err, std::string message) noexcept
365 {
366  m_last_err = err;
367  m_error_message = message;
368 }
369 
372 {
373  /* if we have a local error, return that. */
374  if (m_last_err != ERR_BACKEND_NO_ERR)
375  return m_last_err;
376  auto qof_be = qof_book_get_backend (m_book);
377  if (qof_be == nullptr) return ERR_BACKEND_NO_ERR;
378 
379  m_last_err = qof_be->get_error();
380  return m_last_err;
381 }
382 
383 const std::string&
384 QofSessionImpl::get_error_message () const noexcept
385 {
386  return m_error_message;
387 }
388 
390 QofSessionImpl::pop_error () noexcept
391 {
392  QofBackendError err {get_error ()};
393  clear_error ();
394  return err;
395 }
396 
397 /* Accessors (getters/setters) -----------------------------*/
398 
399 QofBook *
400 QofSessionImpl::get_book () const noexcept
401 {
402  if (!m_book) return nullptr;
403  if (qof_book_is_open (m_book))
404  return m_book;
405  return nullptr;
406 }
407 
408 QofBackend *
409 QofSession::get_backend () const noexcept
410 {
411  return m_backend;
412 }
413 
414 const std::string&
415 QofSessionImpl::get_file_path () const noexcept
416 {
417  auto backend = qof_book_get_backend (m_book);
418  if (!backend) return empty_string;
419  return backend->get_uri();
420 }
421 
422 std::string const &
423 QofSessionImpl::get_uri () const noexcept
424 {
425  return m_uri;
426 }
427 
428 bool
429 QofSessionImpl::is_saving () const noexcept
430 {
431  return m_saving;
432 }
433 
434 /* Manipulators (save, load, etc.) -------------------------*/
435 
436 void
437 QofSessionImpl::save (QofPercentageFunc percentage_func) noexcept
438 {
439  if (!qof_book_session_not_saved (m_book)) //Clean book, nothing to do.
440  return;
441  m_saving = true;
442  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  if (m_backend)
451  {
452  /* if invoked as SaveAs(), then backend not yet set */
453  if (qof_book_get_backend (m_book) != m_backend)
454  qof_book_set_backend (m_book, m_backend);
455  m_backend->set_percentage(percentage_func);
456  m_backend->sync(m_book);
457  auto err = m_backend->get_error();
458  if (err != ERR_BACKEND_NO_ERR)
459  {
460  push_error (err, {});
461  m_saving = false;
462  return;
463  }
464  /* If we got to here, then the backend saved everything
465  * just fine, and we are done. So return. */
466  clear_error ();
467  LEAVE("Success");
468  }
469  else
470  {
471  push_error (ERR_BACKEND_NO_HANDLER, "failed to load backend");
472  LEAVE("error -- No backend!");
473  }
474  m_saving = false;
475 }
476 
477 void
478 QofSessionImpl::safe_save (QofPercentageFunc percentage_func) noexcept
479 {
480  if (!(m_backend && m_book)) return;
481  if (qof_book_get_backend (m_book) != m_backend)
482  qof_book_set_backend (m_book, m_backend);
483  m_backend->set_percentage(percentage_func);
484  m_backend->safe_sync(get_book ());
485  auto err = m_backend->get_error();
486  auto msg = m_backend->get_message();
487  if (err != ERR_BACKEND_NO_ERR)
488  {
489  m_uri = "";
490  push_error (err, msg);
491  }
492 }
493 
494 void
495 QofSessionImpl::ensure_all_data_loaded () noexcept
496 {
497  if (!(m_backend && m_book)) return;
498  if (qof_book_get_backend (m_book) != m_backend)
499  qof_book_set_backend (m_book, m_backend);
500  m_backend->load(m_book, LOAD_TYPE_LOAD_ALL);
501  push_error (m_backend->get_error(), {});
502 }
503 
504 void
506 {
507  ENTER ("sess1=%p sess2=%p", this, &other);
508  // don't swap (that is, double-swap) read_only flags
509  if (m_book && other.m_book)
510  qof_book_swap_books_readonly (m_book, other.m_book);
511  std::swap (m_book, other.m_book);
512  auto mybackend = qof_book_get_backend (m_book);
513  qof_book_set_backend (m_book, qof_book_get_backend (other.m_book));
514  qof_book_set_backend (other.m_book, mybackend);
515  LEAVE (" ");
516 }
517 
518 bool
519 QofSessionImpl::events_pending () const noexcept
520 {
521  return false;
522 }
523 
524 bool
525 QofSessionImpl::process_events () const noexcept
526 {
527  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 QofSessionImpl::export_session (QofSessionImpl & real_session,
536  QofPercentageFunc percentage_func) noexcept
537 {
538  auto real_book = real_session.get_book ();
539  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  if (!m_backend) return false;
546 
547  m_backend->set_percentage(percentage_func);
548 
549  m_backend->export_coa(real_book);
550  auto err = m_backend->get_error();
551  if (err != ERR_BACKEND_NO_ERR)
552  return false;
553  return true;
554 }
555 
556 /* C Wrapper Functions */
557 /* ====================================================================== */
558 
559 const char *
560 qof_session_get_error_message (const QofSession * session)
561 {
562  if (!session) return "";
563  return session->get_error_message ().c_str ();
564 }
565 
567 qof_session_pop_error (QofSession * session)
568 {
569  if (!session) return ERR_BACKEND_NO_BACKEND;
570  return session->pop_error ();
571 }
572 
573 QofBook *
574 qof_session_get_book (const QofSession *session)
575 {
576  if (!session) return NULL;
577  return session->get_book ();
578 }
579 
580 const char *
581 qof_session_get_file_path (const QofSession *session)
582 {
583  if (!session) return nullptr;
584  auto& path{session->get_file_path()};
585  return path.empty() ? nullptr : path.c_str ();
586 }
587 
588 void
590 {
591  if (session == nullptr) return;
592  return session->ensure_all_data_loaded ();
593 }
594 
595 const char *
596 qof_session_get_url (const QofSession *session)
597 {
598  if (!session) return NULL;
599  return session->get_uri ().c_str ();
600 }
601 
602 QofBackend *
603 qof_session_get_backend (const QofSession *session)
604 {
605  if (!session) return NULL;
606  return session->get_backend ();
607 }
608 
609 void
610 qof_session_begin (QofSession *session, const char * uri, SessionOpenMode mode)
611 {
612  if (!session) return;
613  session->begin(uri, mode);
614 }
615 
616 void
617 qof_session_load (QofSession *session,
618  QofPercentageFunc percentage_func)
619 {
620  if (!session) return;
621  session->load (percentage_func);
622 }
623 
624 void
625 qof_session_save (QofSession *session,
626  QofPercentageFunc percentage_func)
627 {
628  if (!session) return;
629  session->save (percentage_func);
630 }
631 
632 void
633 qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
634 {
635  if (!session) return;
636  session->safe_save (percentage_func);
637 }
638 
639 gboolean
640 qof_session_save_in_progress(const QofSession *session)
641 {
642  if (!session) return false;
643  return session->is_saving ();
644 }
645 
646 void
647 qof_session_end (QofSession *session)
648 {
649  if (!session) return;
650  session->end ();
651 }
652 
653 void
654 qof_session_swap_data (QofSession *session_1, QofSession *session_2)
655 {
656  if (session_1 == session_2) return;
657  if (!session_1 || !session_2) return;
658  session_1->swap_books (*session_2);
659 }
660 
661 gboolean
662 qof_session_events_pending (const QofSession *session)
663 {
664  if (!session) return false;
665  return session->events_pending ();
666 }
667 
668 gboolean
669 qof_session_process_events (QofSession *session)
670 {
671  if (!session) return FALSE;
672  return session->process_events ();
673 }
674 
675 gboolean
676 qof_session_export (QofSession *tmp_session,
677  QofSession *real_session,
678  QofPercentageFunc percentage_func)
679 {
680  if ((!tmp_session) || (!real_session)) return FALSE;
681  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 void qof_session_load_backend (QofSession * session, const char * access_method)
689 {
690  session->load_backend (access_method);
691 }
692 
693 static void
694 qof_session_clear_error (QofSession * session)
695 {
696  session->clear_error ();
697 }
698 
699 static void
700 qof_session_destroy_backend (QofSession * session)
701 {
702  session->destroy_backend ();
703 }
704 
705 void qof_session_set_uri (QofSession * session, char const * uri)
706 {
707  if (!uri)
708  session->m_uri = "";
709  else
710  session->m_uri = uri;
711 }
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 init_static_qofsession_pointers (void)
720 {
721  p_qof_session_load_backend = &qof_session_load_backend;
722  p_qof_session_clear_error = &qof_session_clear_error;
723  p_qof_session_destroy_backend = &qof_session_destroy_backend;
724  p_qof_session_set_uri = &qof_session_set_uri;
725 }
726 
728 qof_session_get_error (QofSession * session)
729 {
730  if (!session) return ERR_BACKEND_NO_BACKEND;
731  return session->get_error();
732 }
void qof_session_save(QofSession *session, QofPercentageFunc percentage_func)
The qof_session_save() method will commit all changes that have been made to the session.
Definition: qofsession.cpp:625
void swap_books(QofSessionImpl &) noexcept
Swap books with another session.
Definition: qofsession.cpp:505
gboolean qof_session_save_in_progress(const QofSession *session)
The qof_session_not_saved() subroutine will return TRUE if any data in the session hasn&#39;t been saved ...
Definition: qofsession.cpp:640
void(* QofPercentageFunc)(const char *message, double percent)
The qof_session_load() method causes the QofBook to be made ready to to use with this URL/datastore...
Definition: qofsession.h:199
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gboolean qof_session_events_pending(const QofSession *session)
The qof_session_events_pending() method will return TRUE if the backend has pending events which must...
Definition: qofsession.cpp:662
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
void qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
A special version of save used in the sql backend which moves the existing tables aside...
Definition: qofsession.cpp:633
void qof_backend_register_provider(QofBackendProvider_ptr &&prov)
Let the system know about a new provider of backends.
Definition: qofsession.cpp:91
void end() noexcept
Terminates the current backend.
Definition: qofsession.cpp:335
void qof_session_begin(QofSession *session, const char *uri, SessionOpenMode mode)
Begins a new session.
Definition: qofsession.cpp:610
QofBook * qof_book_new(void)
Allocate, initialise and return a new QofBook.
Definition: qofbook.cpp:290
database is old and needs upgrading
Definition: qofbackend.h:113
gchar * gnc_uri_get_path(const gchar *uri)
Extracts the path part from a uri.
Can&#39;t parse url.
Definition: qofbackend.h:62
in use by another user (ETXTBSY)
Definition: qofbackend.h:66
Create a new store at the URI.
Definition: qofsession.h:126
const char * qof_session_get_file_path(const QofSession *session)
The qof_session_get_file_path() routine returns the fully-qualified file path for the session...
Definition: qofsession.cpp:581
void qof_session_ensure_all_data_loaded(QofSession *session)
Ensure all of the data is loaded from the session.
Definition: qofsession.cpp:589
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
file will be upgraded and not be able to be read by prior versions - warn users
Definition: qofbackend.h:103
the Core Object Registration/Lookup Private Interface
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
gboolean qof_book_empty(const QofBook *book)
Check if the book has had anything loaded into it.
Definition: qofbook.cpp:511
std::string const & get_uri() const noexcept
We return by reference so that a pointer to the data of the string lives long enough to make it back ...
Definition: qofsession.cpp:423
file does not specify encoding
Definition: qofbackend.h:99
database is newer, we can&#39;t write to it
Definition: qofbackend.h:114
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Definition: qofsession.cpp:574
QofBackendError qof_session_pop_error(QofSession *session)
The qof_session_pop_error() routine can be used to obtain the reason for any failure.
Definition: qofsession.cpp:567
GList * qof_backend_get_registered_access_method_list(void)
Return a list of strings for the registered access methods.
Definition: qofsession.cpp:104
QofBackendError get_error() noexcept
Returns and clears the local cached error.
Definition: qofsession.cpp:371
QofBackendError qof_session_get_error(QofSession *session)
The qof_session_get_error() routine can be used to obtain the reason for any failure.
Definition: qofsession.cpp:728
void qof_session_swap_data(QofSession *session_1, QofSession *session_2)
The qof_session_swap_data () method swaps the book of the two given sessions.
Definition: qofsession.cpp:654
no backend handler found for this access method (ENOSYS)
Definition: qofbackend.h:60
gboolean qof_book_session_not_saved(const QofBook *book)
qof_book_not_saved() returns the value of the session_dirty flag, set when changes to any object in t...
Definition: qofbook.cpp:375
virtual void load(QofBook *, QofBackendLoadType)=0
Load the minimal set of application data needed for the application to be operable at initial startup...
QofBook reference.
Definition: qofbook-p.hpp:46
SessionOpenMode
Mode for opening sessions.
Definition: qofsession.h:120
Backend * pointer was unexpectedly null.
Definition: qofbackend.h:61
void begin(const char *new_uri, SessionOpenMode mode) noexcept
Begin this session.
Definition: qofsession.cpp:251
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Utility functions for convert uri in separate components and back.
void qof_session_end(QofSession *session)
The qof_session_end() method will release the session lock.
Definition: qofsession.cpp:647
QofBackend * qof_book_get_backend(const QofBook *book)
Retrieve the backend used by this book.
Definition: qofbook.cpp:440
QofBackend * qof_session_get_backend(const QofSession *session)
Returns the qof session&#39;s backend.
Definition: qofsession.cpp:603
gboolean qof_session_process_events(QofSession *session)
The qof_session_process_events() method will process any events indicated by the qof_session_events_p...
Definition: qofsession.cpp:669
file version so old we can&#39;t read it
Definition: qofbackend.h:93
Open will fail if the URI doesn&#39;t exist or is locked.
Definition: qofsession.h:124
void qof_book_destroy(QofBook *book)
End any editing sessions associated with book, and free all memory associated with it...
Definition: qofbook.cpp:331
QofBackendError get_error()
Retrieve the currently-stored error and clear it.
Definition: qof-backend.cpp:64