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 
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 get_providers (void)
79 {
80  return s_providers;
81 }
82 
83 bool
84 get_providers_initialized (void)
85 {
86  return !s_providers.empty();
87 }
88 
89 void
90 qof_backend_register_provider (QofBackendProvider_ptr&& prov)
91 {
92  s_providers.emplace_back(std::move(prov));
93 }
94 
95 void
96 qof_backend_unregister_all_providers ()
97 {
98  s_providers.clear ();
99 }
100 
101 /* Called from C so we have to keep the GList for now. */
102 GList*
104 {
105  GList* list = NULL;
106  std::for_each(s_providers.begin(), s_providers.end(),
107  [&list](QofBackendProvider_ptr& provider) {
108  gpointer method = reinterpret_cast<gpointer>(const_cast<char*>(provider->access_method));
109  list = g_list_prepend(list, method);
110  });
111  return list;
112 }
113 
114 /* QofSessionImpl */
115 /* ====================================================================== */
116 /* Constructor/Destructor ----------------------------------*/
117 
118 QofSessionImpl::QofSessionImpl (QofBook* book) noexcept
119  : m_backend {},
120  m_book {book},
121  m_uri {},
122  m_saving {false},
123  m_last_err {},
124  m_error_message {}
125 {
126 }
127 
128 QofSessionImpl::~QofSessionImpl () noexcept
129 {
130  ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
131  end ();
132  destroy_backend ();
133  qof_book_set_backend (m_book, nullptr);
134  qof_book_destroy (m_book);
135  m_book = nullptr;
136  LEAVE ("sess=%p", this);
137 }
138 
139 void
140 qof_session_destroy (QofSession * session)
141 {
142  delete session;
143 }
144 
145 QofSession *
146 qof_session_new (QofBook* book)
147 {
148  return new QofSessionImpl(book);
149 }
150 
151 void
152 QofSessionImpl::destroy_backend () noexcept
153 {
154  if (m_backend)
155  {
156  clear_error ();
157  delete m_backend;
158  m_backend = nullptr;
159  qof_book_set_backend (m_book, nullptr);
160  }
161 }
162 
163 /* ====================================================================== */
164 
165 void
166 QofSessionImpl::load_backend (std::string access_method) noexcept
167 {
168  std::ostringstream s;
169  s << " list=" << s_providers.size();
170  ENTER ("%s", s.str().c_str());
171  for (auto const & prov : s_providers)
172  {
173  if (!boost::iequals (access_method, prov->access_method))
174  {
175  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  continue;
178  }
179  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  if (!m_creating && !prov->type_check (m_uri.c_str ()))
183  {
184  PINFO("Provider, %s, reported not being usable for book, %s.",
185  prov->provider_name, m_uri.c_str ());
186  continue;
187  }
188  m_backend = prov->create_backend();
189  LEAVE (" ");
190  return;
191  }
192  std::string msg {"failed to get_backend using access method \"" + access_method + "\""};
193  push_error (ERR_BACKEND_NO_HANDLER, msg);
194  LEAVE (" ");
195 }
196 
197 void
198 QofSessionImpl::load (QofPercentageFunc percentage_func) noexcept
199 {
200  /* We must have an empty book to load into or bad things will happen. */
201  g_return_if_fail(m_book && qof_book_empty(m_book));
202 
203  if (!m_uri.size ()) return;
204  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  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  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  if (m_backend)
224  {
225  m_backend->set_percentage(percentage_func);
226  m_backend->load (m_book, LOAD_TYPE_INITIAL_LOAD);
227  push_error (m_backend->get_error(), {});
228  }
229 
230  auto err = get_error ();
231  if ((err != ERR_BACKEND_NO_ERR) &&
232  (err != ERR_FILEIO_FILE_TOO_OLD) &&
233  (err != ERR_FILEIO_NO_ENCODING) &&
234  (err != ERR_FILEIO_FILE_UPGRADE) &&
235  (err != ERR_SQL_DB_TOO_OLD) &&
236  (err != ERR_SQL_DB_TOO_NEW))
237  {
238  // Something failed, delete and restore new ones.
239  destroy_backend();
240  qof_book_destroy (m_book);
241  m_book = qof_book_new();
242  LEAVE ("error from backend %d", get_error ());
243  return;
244  }
245 
246  LEAVE ("sess = %p, uri=%s", this, m_uri.c_str ());
247 }
248 
249 void
250 QofSessionImpl::begin (const char* new_uri, SessionOpenMode mode) noexcept
251 {
252 
253 
254  ENTER (" sess=%p mode=%d, URI=%s", this, mode, new_uri);
255  clear_error ();
256  /* Check to see if this session is already open */
257  if (m_uri.size ())
258  {
259  if (ERR_BACKEND_NO_ERR != get_error ())
260  push_error (ERR_BACKEND_LOCKED, {});
261  LEAVE("push error book is already open ");
262  return;
263  }
264 
265  /* seriously invalid */
266  if (!new_uri)
267  {
268  if (ERR_BACKEND_NO_ERR != get_error ())
269  push_error (ERR_BACKEND_BAD_URL, {});
270  LEAVE("push error missing new_uri");
271  return;
272  }
273 
274  char * scheme {g_uri_parse_scheme (new_uri)};
275  char * filename {nullptr};
276  if (g_strcmp0 (scheme, "file") == 0)
277  filename = g_filename_from_uri (new_uri, nullptr, nullptr);
278  else if (!scheme)
279  filename = g_strdup (new_uri);
280 
281  if (filename && g_file_test (filename, G_FILE_TEST_IS_DIR))
282  {
283  if (ERR_BACKEND_NO_ERR == get_error ())
284  push_error (ERR_BACKEND_BAD_URL, {});
285  g_free (filename);
286  g_free (scheme);
287  LEAVE("Can't open a directory");
288  return;
289  }
290  /* destroy the old backend */
291  destroy_backend ();
292  /* Store the session URL */
293  m_uri = new_uri;
294  m_creating = mode == SESSION_NEW_STORE || mode == SESSION_NEW_OVERWRITE;
295  if (filename)
296  load_backend ("file");
297  else /* access method found, load appropriate backend */
298  load_backend (scheme);
299  g_free (filename);
300  g_free (scheme);
301 
302  /* No backend was found. That's bad. */
303  if (m_backend == nullptr)
304  {
305  m_uri = {};
306  if (ERR_BACKEND_NO_ERR == get_error ())
307  push_error (ERR_BACKEND_BAD_URL, {});
308  LEAVE (" BAD: no backend: sess=%p book-id=%s",
309  this, new_uri);
310  return;
311  }
312 
313  /* If there's a begin method, call that. */
314  m_backend->session_begin(this, m_uri.c_str(), mode);
315  PINFO ("Done running session_begin on backend");
316  QofBackendError const err {m_backend->get_error()};
317  auto msg (m_backend->get_message());
318  if (err != ERR_BACKEND_NO_ERR)
319  {
320  m_uri = {};
321  push_error (err, msg);
322  LEAVE (" backend error %d %s", err, msg.empty() ? "(null)" : msg.c_str());
323  return;
324  }
325  if (!msg.empty())
326  {
327  PWARN("%s", msg.c_str());
328  }
329 
330  LEAVE (" sess=%p book-id=%s", this, new_uri);
331 }
332 
333 void
335 {
336  ENTER ("sess=%p uri=%s", this, m_uri.c_str ());
337  auto backend = qof_book_get_backend (m_book);
338  if (backend != nullptr)
339  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 ('y' == m_book->book_open)
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  std::swap (m_book->read_only, other.m_book->read_only);
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:90
void end() noexcept
Terminates the current backend.
Definition: qofsession.cpp:334
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
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:103
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...
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:250
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
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