GnuCash c935c2f+
Loading...
Searching...
No Matches
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
52static 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
67using ProviderVec = std::vector<QofBackendProvider_ptr>;
68static ProviderVec s_providers;
69static 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
75ProviderVec& get_providers (void );
76bool get_providers_initialized (void );
77
78ProviderVec&
79get_providers (void)
80{
81 return s_providers;
82}
83
84bool
85get_providers_initialized (void)
86{
87 return !s_providers.empty();
88}
89
90void
91qof_backend_register_provider (QofBackendProvider_ptr&& prov)
92{
93 s_providers.emplace_back(std::move(prov));
94}
95
96void
97qof_backend_unregister_all_providers ()
98{
99 s_providers.clear ();
100}
101
102/* Called from C so we have to keep the GList for now. */
103GList*
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
119QofSessionImpl::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
129QofSessionImpl::~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
140void
141qof_session_destroy (QofSession * session)
142{
143 delete session;
144}
145
146QofSession *
147qof_session_new (QofBook* book)
148{
149 return new QofSessionImpl(book);
150}
151
152void
153QofSessionImpl::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
166void
167QofSessionImpl::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
198void
199QofSessionImpl::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
250void
251QofSessionImpl::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
334void
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
347void
348QofSessionImpl::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
363void
364QofSessionImpl::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
383const std::string&
384QofSessionImpl::get_error_message () const noexcept
385{
386 return m_error_message;
387}
388
390QofSessionImpl::pop_error () noexcept
391{
392 QofBackendError err {get_error ()};
393 clear_error ();
394 return err;
395}
396
397/* Accessors (getters/setters) -----------------------------*/
398
399QofBook *
400QofSessionImpl::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
409QofSession::get_backend () const noexcept
410{
411 return m_backend;
412}
413
414const std::string&
415QofSessionImpl::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
422std::string const &
423QofSessionImpl::get_uri () const noexcept
424{
425 return m_uri;
426}
427
428bool
429QofSessionImpl::is_saving () const noexcept
430{
431 return m_saving;
432}
433
434/* Manipulators (save, load, etc.) -------------------------*/
435
436void
437QofSessionImpl::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
477void
478QofSessionImpl::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
494void
495QofSessionImpl::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
504void
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
518bool
519QofSessionImpl::events_pending () const noexcept
520{
521 return false;
522}
523
524bool
525QofSessionImpl::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 */
534bool
535QofSessionImpl::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
559const char *
560qof_session_get_error_message (const QofSession * session)
561{
562 if (!session) return "";
563 return session->get_error_message ().c_str ();
564}
565
567qof_session_pop_error (QofSession * session)
568{
569 if (!session) return ERR_BACKEND_NO_BACKEND;
570 return session->pop_error ();
571}
572
573QofBook *
574qof_session_get_book (const QofSession *session)
575{
576 if (!session) return NULL;
577 return session->get_book ();
578}
579
580const char *
581qof_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
588void
590{
591 if (session == nullptr) return;
592 return session->ensure_all_data_loaded ();
593}
594
595const char *
596qof_session_get_url (const QofSession *session)
597{
598 if (!session) return NULL;
599 return session->get_uri ().c_str ();
600}
601
603qof_session_get_backend (const QofSession *session)
604{
605 if (!session) return NULL;
606 return session->get_backend ();
607}
608
609void
610qof_session_begin (QofSession *session, const char * uri, SessionOpenMode mode)
611{
612 if (!session) return;
613 session->begin(uri, mode);
614}
615
616void
617qof_session_load (QofSession *session,
618 QofPercentageFunc percentage_func)
619{
620 if (!session) return;
621 session->load (percentage_func);
622}
623
624void
625qof_session_save (QofSession *session,
626 QofPercentageFunc percentage_func)
627{
628 if (!session) return;
629 session->save (percentage_func);
630}
631
632void
633qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
634{
635 if (!session) return;
636 session->safe_save (percentage_func);
637}
638
639gboolean
640qof_session_save_in_progress(const QofSession *session)
641{
642 if (!session) return false;
643 return session->is_saving ();
644}
645
646void
647qof_session_end (QofSession *session)
648{
649 if (!session) return;
650 session->end ();
651}
652
653void
654qof_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
661gboolean
662qof_session_events_pending (const QofSession *session)
663{
664 if (!session) return false;
665 return session->events_pending ();
666}
667
668gboolean
669qof_session_process_events (QofSession *session)
670{
671 if (!session) return FALSE;
672 return session->process_events ();
673}
674
675gboolean
676qof_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
686void init_static_qofsession_pointers (void);
687
688void qof_session_load_backend (QofSession * session, const char * access_method)
689{
690 session->load_backend (access_method);
691}
692
693static void
694qof_session_clear_error (QofSession * session)
695{
696 session->clear_error ();
697}
698
699static void
700qof_session_destroy_backend (QofSession * session)
701{
702 session->destroy_backend ();
703}
704
705void 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
713void (*p_qof_session_load_backend) (QofSession *, const char * access_method);
714void (*p_qof_session_clear_error) (QofSession *);
715void (*p_qof_session_destroy_backend) (QofSession *);
716void (*p_qof_session_set_uri) (QofSession *, char const * uri);
717
718void
719init_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
728qof_session_get_error (QofSession * session)
729{
730 if (!session) return ERR_BACKEND_NO_BACKEND;
731 return session->get_error();
732}
Utility functions for convert uri in separate components and back.
QofBackendError qof_session_pop_error(QofSession *session)
The qof_session_pop_error() routine can be used to obtain the reason for any failure.
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.
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.
void qof_session_end(QofSession *session)
The qof_session_end() method will release the session lock.
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition qofbackend.h:58
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't been saved ...
QofBackend * qof_book_get_backend(const QofBook *book)
Retrieve the backend used by this book.
Definition qofbook.cpp:440
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.
QofBackendError qof_session_get_error(QofSession *session)
The qof_session_get_error() routine can be used to obtain the reason for any failure.
QofBackend * qof_session_get_backend(const QofSession *session)
Returns the qof session's backend.
SessionOpenMode
Mode for opening sessions.
Definition qofsession.h:121
void qof_session_begin(QofSession *session, const char *uri, SessionOpenMode mode)
Begins a new session.
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,...
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
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
@ ERR_BACKEND_BAD_URL
Can't parse url.
Definition qofbackend.h:62
@ ERR_BACKEND_NO_HANDLER
no backend handler found for this access method (ENOSYS)
Definition qofbackend.h:60
@ ERR_BACKEND_LOCKED
in use by another user (ETXTBSY)
Definition qofbackend.h:66
@ ERR_BACKEND_NO_BACKEND
Backend * pointer was unexpectedly null.
Definition qofbackend.h:61
@ ERR_FILEIO_NO_ENCODING
file does not specify encoding
Definition qofbackend.h:99
@ ERR_SQL_DB_TOO_OLD
database is old and needs upgrading
Definition qofbackend.h:113
@ ERR_SQL_DB_TOO_NEW
database is newer, we can't write to it
Definition qofbackend.h:114
@ ERR_FILEIO_FILE_UPGRADE
file will be upgraded and not be able to be read by prior versions - warn users
Definition qofbackend.h:103
@ ERR_FILEIO_FILE_TOO_OLD
file version so old we can't read it
Definition qofbackend.h:93
@ SESSION_NEW_STORE
Open will fail if the URI doesn't exist or is locked.
Definition qofsession.h:124
@ SESSION_NEW_OVERWRITE
Create a new store at the URI.
Definition qofsession.h:126
void qof_book_destroy(QofBook *book)
End any editing sessions associated with book, and free all memory associated with it.
Definition qofbook.cpp:331
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
QofBook * qof_book_new(void)
Allocate, initialise and return a new QofBook.
Definition qofbook.cpp:290
gboolean qof_book_empty(const QofBook *book)
Check if the book has had anything loaded into it.
Definition qofbook.cpp:511
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
virtual void load(QofBook *, QofBackendLoadType)=0
Load the minimal set of application data needed for the application to be operable at initial startup...
QofBackendError get_error()
Retrieve the currently-stored error and clear it.
gchar * gnc_uri_get_path(const gchar *uri)
Extracts the path part from a uri.
the Core Object Registration/Lookup Private Interface
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...
gboolean qof_session_process_events(QofSession *session)
The qof_session_process_events() method will process any events indicated by the qof_session_events_p...
GList * qof_backend_get_registered_access_method_list(void)
Return a list of strings for the registered access methods.
void qof_session_ensure_all_data_loaded(QofSession *session)
Ensure all of the data is loaded from the session.
void qof_backend_register_provider(QofBackendProvider_ptr &&prov)
Let the system know about a new provider of backends.
QofBook reference.
Definition qofbook-p.hpp:47
void swap_books(QofSessionImpl &) noexcept
Swap books with another session.
void begin(const char *new_uri, SessionOpenMode mode) noexcept
Begin this session.
QofBackendError get_error() noexcept
Returns and clears the local cached error.
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 ...
void end() noexcept
Terminates the current backend.