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.h"
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  auto backend = qof_book_get_backend (m_book);
339  if (backend != nullptr)
340  backend->session_end();
341  clear_error ();
342  m_uri.clear();
343  LEAVE ("sess=%p uri=%s", this, m_uri.c_str ());
344 }
345 
346 /* error handling functions --------------------------------*/
347 
348 void
349 QofSessionImpl::clear_error () noexcept
350 {
351  m_last_err = ERR_BACKEND_NO_ERR;
352  m_error_message = {};
353 
354  /* pop the stack on the backend as well. */
355  if (auto backend = qof_book_get_backend (m_book))
356  {
357  QofBackendError err = ERR_BACKEND_NO_ERR;
358  do
359  err = backend->get_error();
360  while (err != ERR_BACKEND_NO_ERR);
361  }
362 }
363 
364 void
365 QofSessionImpl::push_error (QofBackendError const err, std::string message) noexcept
366 {
367  m_last_err = err;
368  m_error_message = message;
369 }
370 
373 {
374  /* if we have a local error, return that. */
375  if (m_last_err != ERR_BACKEND_NO_ERR)
376  return m_last_err;
377  auto qof_be = qof_book_get_backend (m_book);
378  if (qof_be == nullptr) return ERR_BACKEND_NO_ERR;
379 
380  m_last_err = qof_be->get_error();
381  return m_last_err;
382 }
383 
384 const std::string&
385 QofSessionImpl::get_error_message () const noexcept
386 {
387  return m_error_message;
388 }
389 
391 QofSessionImpl::pop_error () noexcept
392 {
393  QofBackendError err {get_error ()};
394  clear_error ();
395  return err;
396 }
397 
398 /* Accessors (getters/setters) -----------------------------*/
399 
400 QofBook *
401 QofSessionImpl::get_book () const noexcept
402 {
403  if (!m_book) return nullptr;
404  if ('y' == m_book->book_open)
405  return m_book;
406  return nullptr;
407 }
408 
409 QofBackend *
410 QofSession::get_backend () const noexcept
411 {
412  return m_backend;
413 }
414 
415 const std::string&
416 QofSessionImpl::get_file_path () const noexcept
417 {
418  auto backend = qof_book_get_backend (m_book);
419  if (!backend) return empty_string;
420  return backend->get_uri();
421 }
422 
423 std::string const &
424 QofSessionImpl::get_uri () const noexcept
425 {
426  return m_uri;
427 }
428 
429 bool
430 QofSessionImpl::is_saving () const noexcept
431 {
432  return m_saving;
433 }
434 
435 /* Manipulators (save, load, etc.) -------------------------*/
436 
437 void
438 QofSessionImpl::save (QofPercentageFunc percentage_func) noexcept
439 {
440  if (!qof_book_session_not_saved (m_book)) //Clean book, nothing to do.
441  return;
442  m_saving = true;
443  ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
444 
445  /* If there is a backend, the book is dirty, and the backend is reachable
446  * (i.e. we can communicate with it), then synchronize with the backend. If
447  * we cannot contact the backend (e.g. because we've gone offline, the
448  * network has crashed, etc.) then raise an error so that the controlling
449  * dialog can offer the user a chance to save in a different way.
450  */
451  if (m_backend)
452  {
453  /* if invoked as SaveAs(), then backend not yet set */
454  if (qof_book_get_backend (m_book) != m_backend)
455  qof_book_set_backend (m_book, m_backend);
456  m_backend->set_percentage(percentage_func);
457  m_backend->sync(m_book);
458  auto err = m_backend->get_error();
459  if (err != ERR_BACKEND_NO_ERR)
460  {
461  push_error (err, {});
462  m_saving = false;
463  return;
464  }
465  /* If we got to here, then the backend saved everything
466  * just fine, and we are done. So return. */
467  clear_error ();
468  LEAVE("Success");
469  }
470  else
471  {
472  push_error (ERR_BACKEND_NO_HANDLER, "failed to load backend");
473  LEAVE("error -- No backend!");
474  }
475  m_saving = false;
476 }
477 
478 void
479 QofSessionImpl::safe_save (QofPercentageFunc percentage_func) noexcept
480 {
481  if (!(m_backend && m_book)) return;
482  if (qof_book_get_backend (m_book) != m_backend)
483  qof_book_set_backend (m_book, m_backend);
484  m_backend->set_percentage(percentage_func);
485  m_backend->safe_sync(get_book ());
486  auto err = m_backend->get_error();
487  auto msg = m_backend->get_message();
488  if (err != ERR_BACKEND_NO_ERR)
489  {
490  m_uri = "";
491  push_error (err, msg);
492  }
493 }
494 
495 void
496 QofSessionImpl::ensure_all_data_loaded () noexcept
497 {
498  if (!(m_backend && m_book)) return;
499  if (qof_book_get_backend (m_book) != m_backend)
500  qof_book_set_backend (m_book, m_backend);
501  m_backend->load(m_book, LOAD_TYPE_LOAD_ALL);
502  push_error (m_backend->get_error(), {});
503 }
504 
505 void
507 {
508  ENTER ("sess1=%p sess2=%p", this, &other);
509  // don't swap (that is, double-swap) read_only flags
510  if (m_book && other.m_book)
511  std::swap (m_book->read_only, other.m_book->read_only);
512  std::swap (m_book, other.m_book);
513  auto mybackend = qof_book_get_backend (m_book);
514  qof_book_set_backend (m_book, qof_book_get_backend (other.m_book));
515  qof_book_set_backend (other.m_book, mybackend);
516  LEAVE (" ");
517 }
518 
519 bool
520 QofSessionImpl::events_pending () const noexcept
521 {
522  return false;
523 }
524 
525 bool
526 QofSessionImpl::process_events () const noexcept
527 {
528  return false;
529 }
530 
531 /* XXX This exports the list of accounts to a file. It does not
532  * export any transactions. It's a place-holder until full
533  * book-closing is implemented.
534  */
535 bool
536 QofSessionImpl::export_session (QofSessionImpl & real_session,
537  QofPercentageFunc percentage_func) noexcept
538 {
539  auto real_book = real_session.get_book ();
540  ENTER ("tmp_session=%p real_session=%p book=%p uri=%s",
541  this, &real_session, real_book, m_uri.c_str ());
542 
543  /* There must be a backend or else. (It should always be the file
544  * backend too.)
545  */
546  if (!m_backend) return false;
547 
548  m_backend->set_percentage(percentage_func);
549 
550  m_backend->export_coa(real_book);
551  auto err = m_backend->get_error();
552  if (err != ERR_BACKEND_NO_ERR)
553  return false;
554  return true;
555 }
556 
557 /* C Wrapper Functions */
558 /* ====================================================================== */
559 
560 const char *
561 qof_session_get_error_message (const QofSession * session)
562 {
563  if (!session) return "";
564  return session->get_error_message ().c_str ();
565 }
566 
568 qof_session_pop_error (QofSession * session)
569 {
570  if (!session) return ERR_BACKEND_NO_BACKEND;
571  return session->pop_error ();
572 }
573 
574 QofBook *
575 qof_session_get_book (const QofSession *session)
576 {
577  if (!session) return NULL;
578  return session->get_book ();
579 }
580 
581 const char *
582 qof_session_get_file_path (const QofSession *session)
583 {
584  if (!session) return nullptr;
585  auto& path{session->get_file_path()};
586  return path.empty() ? nullptr : path.c_str ();
587 }
588 
589 void
591 {
592  if (session == nullptr) return;
593  return session->ensure_all_data_loaded ();
594 }
595 
596 const char *
597 qof_session_get_url (const QofSession *session)
598 {
599  if (!session) return NULL;
600  return session->get_uri ().c_str ();
601 }
602 
603 QofBackend *
604 qof_session_get_backend (const QofSession *session)
605 {
606  if (!session) return NULL;
607  return session->get_backend ();
608 }
609 
610 void
611 qof_session_begin (QofSession *session, const char * uri, SessionOpenMode mode)
612 {
613  if (!session) return;
614  session->begin(uri, mode);
615 }
616 
617 void
618 qof_session_load (QofSession *session,
619  QofPercentageFunc percentage_func)
620 {
621  if (!session) return;
622  session->load (percentage_func);
623 }
624 
625 void
626 qof_session_save (QofSession *session,
627  QofPercentageFunc percentage_func)
628 {
629  if (!session) return;
630  session->save (percentage_func);
631 }
632 
633 void
634 qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
635 {
636  if (!session) return;
637  session->safe_save (percentage_func);
638 }
639 
640 gboolean
641 qof_session_save_in_progress(const QofSession *session)
642 {
643  if (!session) return false;
644  return session->is_saving ();
645 }
646 
647 void
648 qof_session_end (QofSession *session)
649 {
650  if (!session) return;
651  session->end ();
652 }
653 
654 void
655 qof_session_swap_data (QofSession *session_1, QofSession *session_2)
656 {
657  if (session_1 == session_2) return;
658  if (!session_1 || !session_2) return;
659  session_1->swap_books (*session_2);
660 }
661 
662 gboolean
663 qof_session_events_pending (const QofSession *session)
664 {
665  if (!session) return false;
666  return session->events_pending ();
667 }
668 
669 gboolean
670 qof_session_process_events (QofSession *session)
671 {
672  if (!session) return FALSE;
673  return session->process_events ();
674 }
675 
676 gboolean
677 qof_session_export (QofSession *tmp_session,
678  QofSession *real_session,
679  QofPercentageFunc percentage_func)
680 {
681  if ((!tmp_session) || (!real_session)) return FALSE;
682  return tmp_session->export_session (*real_session, percentage_func);
683 }
684 
685 /* ================= Static function access for testing ================= */
686 
687 void init_static_qofsession_pointers (void);
688 
689 void qof_session_load_backend (QofSession * session, const char * access_method)
690 {
691  session->load_backend (access_method);
692 }
693 
694 static void
695 qof_session_clear_error (QofSession * session)
696 {
697  session->clear_error ();
698 }
699 
700 static void
701 qof_session_destroy_backend (QofSession * session)
702 {
703  session->destroy_backend ();
704 }
705 
706 void qof_session_set_uri (QofSession * session, char const * uri)
707 {
708  if (!uri)
709  session->m_uri = "";
710  else
711  session->m_uri = uri;
712 }
713 
714 void (*p_qof_session_load_backend) (QofSession *, const char * access_method);
715 void (*p_qof_session_clear_error) (QofSession *);
716 void (*p_qof_session_destroy_backend) (QofSession *);
717 void (*p_qof_session_set_uri) (QofSession *, char const * uri);
718 
719 void
720 init_static_qofsession_pointers (void)
721 {
722  p_qof_session_load_backend = &qof_session_load_backend;
723  p_qof_session_clear_error = &qof_session_clear_error;
724  p_qof_session_destroy_backend = &qof_session_destroy_backend;
725  p_qof_session_set_uri = &qof_session_set_uri;
726 }
727 
729 qof_session_get_error (QofSession * session)
730 {
731  if (!session) return ERR_BACKEND_NO_BACKEND;
732  return session->get_error();
733 }
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:626
void swap_books(QofSessionImpl &) noexcept
Swap books with another session.
Definition: qofsession.cpp:506
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:641
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:663
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:634
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:611
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:582
void qof_session_ensure_all_data_loaded(QofSession *session)
Ensure all of the data is loaded from the session.
Definition: qofsession.cpp:590
#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:424
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:575
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:568
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:372
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:729
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:655
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...
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:648
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:604
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:670
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