void qof_session_swap_data (QofSession *session_1, QofSession *session_2) { GList *books_1, *books_2, *node; if (session_1 == session_2) return; if (!session_1 || !session_2) return; ENTER ("sess1=%p sess2=%p", session_1, session_2); books_1 = session_1->books; books_2 = session_2->books; session_1->books = books_2; session_2->books = books_1; for (node = books_1; node; node = node->next) { QofBook *book_1 = node->data; qof_book_set_backend (book_1, session_2->backend); } for (node = books_2; node; node = node->next) { QofBook *book_2 = node->data; qof_book_set_backend (book_2, session_1->backend); } LEAVE (" "); }
void qof_session_add_book (QofSession *session, QofBook *addbook) { GList *node; if (!session) return; ENTER (" sess=%p book=%p", session, addbook); /* See if this book is already there ... */ for (node = session->books; node; node = node->next) { QofBook *book = node->data; if (addbook == book) return; } if ('y' == addbook->book_open) { /* hack alert -- someone should free all the books in the list, * but it should probably not be us ... since the books backends * should be shutdown first, etc */ /* XXX this should probably be an error XXX */ g_list_free (session->books); session->books = g_list_append (NULL, addbook); } else { /* XXX Need to tell the backend to add a book as well */ session->books = g_list_append (session->books, addbook); } qof_book_set_backend (addbook, session->backend); LEAVE (" "); }
void qof_session_destroy (QofSession *session) { GList *node; if (!session) return; ENTER ("sess=%p book_id=%s", session, session->book_id ? session->book_id : "(null)"); qof_session_end (session); /* destroy the backend */ qof_session_destroy_backend(session); for (node = session->books; node; node = node->next) { QofBook *book = node->data; qof_book_set_backend (book, NULL); qof_book_destroy (book); } session->books = NULL; g_free (session); LEAVE ("sess=%p", session); }
static void qof_session_load_backend(QofSession * session, const char * access_method) { GSList *p; QofBackendProvider *prov; char *msg; gboolean prov_type; gboolean (*type_check) (const char*); ENTER (" list=%d, initted=%s", g_slist_length(provider_list), qof_providers_initialized ? "true" : "false"); prov_type = FALSE; if (!qof_providers_initialized) { qof_providers_initialized = TRUE; } p = provider_list; while (p != NULL) { prov = static_cast<QofBackendProvider*>(p->data); /* Does this provider handle the desired access method? */ if (0 == g_ascii_strcasecmp (access_method, prov->access_method)) { /* More than one backend could provide this access method, check file type compatibility. */ type_check = (gboolean (*)(const char*)) prov->check_data_type; if (type_check) { prov_type = (type_check)(session->book_id); if (!prov_type) { PINFO(" %s not usable", prov->provider_name); p = p->next; continue; } } PINFO (" selected %s", prov->provider_name); if (NULL == prov->backend_new) { p = p->next; continue; } /* Use the providers creation callback */ session->backend = (*(prov->backend_new))(); session->backend->provider = prov; /* Tell the book about the backend that they'll be using. */ qof_book_set_backend (session->book, session->backend); LEAVE (" "); return; } p = p->next; } msg = g_strdup_printf("failed to load '%s' using access_method", access_method); qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg); g_free(msg); LEAVE (" "); }
void qof_session_save (QofSession *session, QofPercentageFunc percentage_func) { QofBackend *be; if (!session) return; if (!g_atomic_int_dec_and_test(&session->lock)) goto leave; ENTER ("sess=%p book_id=%s", session, session->book_id ? session->book_id : "(null)"); /* If there is a backend, and the backend is reachable * (i.e. we can communicate with it), then synchronize with * the backend. If we cannot contact the backend (e.g. * because we've gone offline, the network has crashed, etc.) * then give the user the option to save to the local disk. * * hack alert -- FIXME -- XXX the code below no longer * does what the words above say. This needs fixing. */ be = session->backend; if (be) { /* if invoked as SaveAs(), then backend not yet set */ qof_book_set_backend (session->book, be); be->percentage = percentage_func; if (be->sync) { (be->sync)(be, session->book); if (save_error_handler(be, session)) goto leave; } /* If we got to here, then the backend saved everything * just fine, and we are done. So return. */ /* Return the book_id to previous value. */ qof_session_clear_error (session); LEAVE("Success"); goto leave; } else { if (ERR_BACKEND_NO_ERR != qof_session_get_error(session)) { /* push_error strdups, stack const is fine. */ const char *msg = "failed to load backend"; qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); } } LEAVE("error -- No backend!"); leave: g_atomic_int_inc(&session->lock); return; }
void qof_session_destroy (QofSession *session) { if (!session) return; ENTER ("sess=%p book_id=%s", session, session->book_id ? session->book_id : "(null)"); qof_session_end (session); /* destroy the backend */ qof_session_destroy_backend(session); qof_book_set_backend (session->book, NULL); qof_book_destroy (session->book); session->book = NULL; g_free (session); LEAVE ("sess=%p", session); }
void qof_session_load (QofSession *session, QofPercentageFunc percentage_func) { QofBook *newbook, *oldbook; QofBackend *be; QofBackendError err; if (!session) return; if (!session->book_id) return; ENTER ("sess=%p book_id=%s", session, session->book_id ? session->book_id : "(null)"); /* At this point, we should are supposed to have a valid book * id and a lock on the file. */ oldbook = session->book; /* XXX why are we creating a book here? I think the books * need to be handled by the backend ... especially since * the backend may need to load multiple books ... XXX. FIXME. */ newbook = qof_book_new(); session->book = newbook; PINFO ("new book=%p", newbook); qof_session_clear_error (session); /* This code should be sufficient to initialize *any* backend, * whether http, postgres, or anything else that might come along. * Basically, the idea is that by now, a backend has already been * created & set up. At this point, we only need to get the * top-level account group out of the backend, and that is a * generic, backend-independent operation. */ be = session->backend; qof_book_set_backend(newbook, be); /* Starting the session should result in a bunch of accounts * and currencies being downloaded, but probably no transactions; * The GUI will need to do a query for that. */ if (be) { be->percentage = percentage_func; if (be->load) { be->load (be, newbook, LOAD_TYPE_INITIAL_LOAD); qof_session_push_error (session, qof_backend_get_error(be), NULL); } } /* XXX if the load fails, then we try to restore the old set of books; * however, we don't undo the session id (the URL). Thus if the * user attempts to save after a failed load, they weill be trying to * save to some bogus URL. This is wrong. XXX FIXME. */ err = qof_session_get_error(session); if ((err != ERR_BACKEND_NO_ERR) && (err != ERR_FILEIO_FILE_TOO_OLD) && (err != ERR_FILEIO_NO_ENCODING) && (err != ERR_FILEIO_FILE_UPGRADE) && (err != ERR_SQL_DB_TOO_OLD) && (err != ERR_SQL_DB_TOO_NEW)) { /* Something broke, put back the old stuff */ qof_book_set_backend (newbook, NULL); qof_book_destroy (newbook); session->book = oldbook; LEAVE("error from backend %d", qof_session_get_error(session)); return; } qof_book_set_backend (oldbook, NULL); qof_book_destroy (oldbook); LEAVE ("sess = %p, book_id=%s", session, session->book_id ? session->book_id : "(null)"); }
void qof_session_save (QofSession *session, QofPercentageFunc percentage_func) { GList *node; QofBackend *be; gboolean partial, change_backend; QofBackendProvider *prov; GSList *p; QofBook *book, *abook; int err; gint num; char *msg = NULL; char *book_id; if (!session) return; if (!g_atomic_int_dec_and_test(&session->lock)) goto leave; ENTER ("sess=%p book_id=%s", session, session->book_id ? session->book_id : "(null)"); /* Partial book handling. */ book = qof_session_get_book(session); partial = (gboolean)GPOINTER_TO_INT(qof_book_get_data(book, PARTIAL_QOFBOOK)); change_backend = FALSE; msg = g_strdup_printf(" "); book_id = g_strdup(session->book_id); if (partial == TRUE) { if (session->backend && session->backend->provider) { prov = session->backend->provider; if (TRUE == prov->partial_book_supported) { /* if current backend supports partial, leave alone. */ change_backend = FALSE; } else { change_backend = TRUE; } } /* If provider is undefined, assume partial not supported. */ else { change_backend = TRUE; } } if (change_backend == TRUE) { qof_session_destroy_backend(session); if (!qof_providers_initialized) { qof_providers_initialized = TRUE; } p = provider_list; while (p != NULL) { prov = p->data; if (TRUE == prov->partial_book_supported) { /** \todo check the access_method too, not in scope here, yet. */ /* if((TRUE == prov->partial_book_supported) && (0 == g_ascii_strcasecmp (access_method, prov->access_method))) {*/ if (NULL == prov->backend_new) continue; /* Use the providers creation callback */ session->backend = (*(prov->backend_new))(); session->backend->provider = prov; if (session->backend->session_begin) { /* Call begin - backend has been changed, so make sure a file can be written, use ignore_lock and force create */ g_free(session->book_id); session->book_id = NULL; (session->backend->session_begin)(session->backend, session, book_id, TRUE, TRUE, TRUE); PINFO("Done running session_begin on changed backend"); err = qof_backend_get_error(session->backend); msg = qof_backend_get_message(session->backend); if (err != ERR_BACKEND_NO_ERR) { g_free(session->book_id); session->book_id = NULL; qof_session_push_error (session, err, msg); LEAVE("changed backend error %d", err); goto leave; } if (msg != NULL) { PWARN("%s", msg); g_free(msg); msg = NULL; } } /* Tell the books about the backend that they'll be using. */ for (node = session->books; node; node = node->next) { book = node->data; qof_book_set_backend (book, session->backend); } p = NULL; } if (p) { p = p->next; } } if (!session->backend) { if (ERR_BACKEND_NO_ERR != qof_session_get_error(session)) { msg = g_strdup_printf("failed to load backend"); qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); } goto leave; } } /* If there is a backend, and the backend is reachable * (i.e. we can communicate with it), then synchronize with * the backend. If we cannot contact the backend (e.g. * because we've gone offline, the network has crashed, etc.) * then give the user the option to save to the local disk. * * hack alert -- FIXME -- XXX the code below no longer * does what the words above say. This needs fixing. */ be = session->backend; if (be) { for (node = session->books; node; node = node->next) { abook = node->data; /* if invoked as SaveAs(), then backend not yet set */ qof_book_set_backend (abook, be); be->percentage = percentage_func; if (be->sync) { (be->sync)(be, abook); if (save_error_handler(be, session)) goto leave; } } /* If we got to here, then the backend saved everything * just fine, and we are done. So return. */ /* Return the book_id to previous value. */ qof_session_clear_error (session); LEAVE("Success"); goto leave; } else { if (ERR_BACKEND_NO_ERR != qof_session_get_error(session)) { msg = g_strdup_printf("failed to load backend"); qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); } } LEAVE("error -- No backend!"); leave: if (msg != NULL) g_free(msg); g_atomic_int_inc(&session->lock); return; }
static void qof_session_load_backend(QofSession * session, const char * access_method) { GSList *p; GList *node; QofBackendProvider *prov; QofBook *book; char *msg; gint num; gboolean prov_type; gboolean (*type_check) (const char*); gchar *libdir_from_env = NULL; ENTER (" list=%d, initted=%s", g_slist_length(provider_list), qof_providers_initialized ? "true" : "false"); prov_type = FALSE; if (!qof_providers_initialized) { libdir_from_env = g_strdup(g_getenv("QOF_LIB_DIR")); for (num = 0; backend_list[num].filename != NULL; num++) { if (libdir_from_env) { if (!(qof_load_backend_library(libdir_from_env, backend_list[num].filename) || qof_load_backend_library(backend_list[num].libdir, backend_list[num].filename))) { PWARN (" failed to load %s from %s or %s", backend_list[num].filename, libdir_from_env, backend_list[num].libdir); } } else { if (!qof_load_backend_library(backend_list[num].libdir, backend_list[num].filename)) { PWARN (" failed to load %s from %s", backend_list[num].filename, backend_list[num].libdir); } } } g_free(libdir_from_env); qof_providers_initialized = TRUE; } p = provider_list; while (p != NULL) { prov = p->data; /* Does this provider handle the desired access method? */ if (0 == g_ascii_strcasecmp (access_method, prov->access_method)) { /* More than one backend could provide this access method, check file type compatibility. */ type_check = (gboolean (*)(const char*)) prov->check_data_type; if (type_check) { prov_type = (type_check)(session->book_id); if (!prov_type) { PINFO(" %s not usable", prov->provider_name); p = p->next; continue; } } PINFO (" selected %s", prov->provider_name); if (NULL == prov->backend_new) { p = p->next; continue; } /* Use the providers creation callback */ session->backend = (*(prov->backend_new))(); session->backend->provider = prov; /* Tell the books about the backend that they'll be using. */ for (node = session->books; node; node = node->next) { book = node->data; qof_book_set_backend (book, session->backend); } LEAVE (" "); return; } p = p->next; } msg = g_strdup_printf("failed to load '%s' using access_method", access_method); qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg); LEAVE (" "); }