コード例 #1
0
ファイル: qofinstance.c プロジェクト: kleopatra999/gnucash-2
gboolean
qof_commit_edit_part2(QofInstance *inst,
                      void (*on_error)(QofInstance *, QofBackendError),
                      void (*on_done)(QofInstance *),
                      void (*on_free)(QofInstance *))
{
    QofInstancePrivate *priv;
    QofBackend * be;
    gboolean dirty;

    priv = GET_PRIVATE(inst);
    dirty = priv->dirty;

    /* See if there's a backend.  If there is, invoke it. */
    be = qof_book_get_backend(priv->book);
    if (be && qof_backend_commit_exists(be))
    {
        QofBackendError errcode;

        /* clear errors */
        do
        {
            errcode = qof_backend_get_error(be);
        }
        while (ERR_BACKEND_NO_ERR != errcode);

        qof_backend_run_commit(be, inst);
        errcode = qof_backend_get_error(be);
        if (ERR_BACKEND_NO_ERR != errcode)
        {
            /* XXX Should perform a rollback here */
            priv->do_free = FALSE;

            /* Push error back onto the stack */
            qof_backend_set_error (be, errcode);
            if (on_error)
                on_error(inst, errcode);
            return FALSE;
        }
        /* XXX the backend commit code should clear dirty!! */
        priv->dirty = FALSE;
    }
//    if (dirty && qof_get_alt_dirty_mode() &&
//        !(priv->infant && priv->do_free)) {
//      qof_collection_mark_dirty(priv->collection);
//      qof_book_mark_dirty(priv->book);
//    }
    priv->infant = FALSE;

    if (priv->do_free)
    {
        if (on_free)
            on_free(inst);
        return TRUE;
    }

    if (on_done)
        on_done(inst);
    return TRUE;
}
コード例 #2
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
static gboolean
save_error_handler(QofBackend *be, QofSession *session)
{
    QofBackendError err;
    err = qof_backend_get_error(be);

    if (ERR_BACKEND_NO_ERR != err)
    {
        qof_session_push_error (session, err, NULL);
        return TRUE;
    }
    return FALSE;
}
コード例 #3
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
void
qof_session_ensure_all_data_loaded (QofSession *session)
{
    QofBackend* backend;

    if (session == NULL) return;
    backend = qof_session_get_backend(session);
    if (backend == NULL) return;

    if (backend->load == NULL) return;
    backend->load(backend, qof_session_get_book(session), LOAD_TYPE_LOAD_ALL);
    qof_session_push_error (session, qof_backend_get_error(backend), NULL);
}
コード例 #4
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
static void
qof_session_clear_error (QofSession *session)
{
    QofBackendError err;

    session->last_err = ERR_BACKEND_NO_ERR;
    g_free(session->error_message);
    session->error_message = NULL;

    /* pop the stack on the backend as well. */
    if (session->backend)
    {
        do
        {
            err = qof_backend_get_error (session->backend);
        }
        while (ERR_BACKEND_NO_ERR != err);
    }
}
コード例 #5
0
ファイル: qofsession.c プロジェクト: kleopatra999/gnucash-2
void
qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
{
    QofBackend *be = session->backend;
    gint err;
    char *msg = NULL;
    g_return_if_fail( be != NULL );
    g_return_if_fail( be->safe_sync != NULL );
    be->percentage = percentage_func;
    (be->safe_sync)( be, qof_session_get_book( session ));
    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);
    }
}
コード例 #6
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
QofBackendError
qof_session_get_error (QofSession * session)
{
    QofBackendError err;

    if (!session) return ERR_BACKEND_NO_BACKEND;

    /* if we have a local error, return that. */
    if (ERR_BACKEND_NO_ERR != session->last_err)
    {
        return session->last_err;
    }

    /* maybe we should return a no-backend error ??? */
    if (! session->backend) return ERR_BACKEND_NO_ERR;

    err = qof_backend_get_error (session->backend);
    session->last_err = err;
    return err;
}
コード例 #7
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
/* XXX This exports the list of accounts to a file.  It does not
 * export any transactions.  It's a place-holder until full
 * book-closing is implemented.
 */
gboolean
qof_session_export (QofSession *tmp_session,
                    QofSession *real_session,
                    QofPercentageFunc percentage_func)
{
    QofBook *book, *book2;
    QofBackend *be;

    if ((!tmp_session) || (!real_session)) return FALSE;

    book = qof_session_get_book (real_session);
    ENTER ("tmp_session=%p real_session=%p book=%p book_id=%s",
           tmp_session, real_session, book,
           qof_session_get_url(tmp_session)
           ? qof_session_get_url(tmp_session) : "(null)");

    /* There must be a backend or else.  (It should always be the file
     * backend too.)
     */
    book2 = qof_session_get_book(tmp_session);
    be = qof_book_get_backend(book2);
    if (!be)
        return FALSE;

    be->percentage = percentage_func;
    if (be->export_fn)
    {
        int err;

        (be->export_fn)(be, book);
        err = qof_backend_get_error(be);

        if (ERR_BACKEND_NO_ERR != err)
        {
            return FALSE;
        }
    }

    return TRUE;
}
コード例 #8
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
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)");
}
コード例 #9
0
ファイル: qofsession.cpp プロジェクト: Isendir/gnucash
void
qof_session_begin (QofSession *session, const char * book_id,
                   gboolean ignore_lock, gboolean create, gboolean force)
{
    gchar *scheme = NULL, *filename = NULL;

    if (!session) return;

    ENTER (" sess=%p ignore_lock=%d, book-id=%s",
           session, ignore_lock,
           book_id ? book_id : "(null)");

    /* Clear the error condition of previous errors */
    qof_session_clear_error (session);

    /* Check to see if this session is already open */
    if (session->book_id)
    {
        if (ERR_BACKEND_NO_ERR != qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_LOCKED, NULL);
        LEAVE("push error book is already open ");
        return;
    }

    /* seriously invalid */
    if (!book_id)
    {
        if (ERR_BACKEND_NO_ERR != qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
        LEAVE("push error missing book_id");
        return;
    }
    scheme = g_uri_parse_scheme (book_id);
    if (g_strcmp0 (scheme, "file") == 0)
        filename = g_filename_from_uri (book_id, NULL, NULL);
    else if (!scheme)
        filename = g_strdup (book_id);

    if (filename && g_file_test (filename, G_FILE_TEST_IS_DIR))
    {
        if (ERR_BACKEND_NO_ERR == qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
        g_free (filename);
        g_free (scheme);
        LEAVE("Can't open a directory");
        return;
    }


    /* destroy the old backend */
    qof_session_destroy_backend(session);

    /* Store the session URL  */
    session->book_id = g_strdup (book_id);

    if (filename)
        qof_session_load_backend(session, "file");
    else                       /* access method found, load appropriate backend */
        qof_session_load_backend(session, scheme);
    g_free (filename);
    g_free (scheme);

    /* No backend was found. That's bad. */
    if (NULL == session->backend)
    {
        g_free(session->book_id);
        session->book_id = NULL;
        if (ERR_BACKEND_NO_ERR == qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
        LEAVE (" BAD: no backend: sess=%p book-id=%s",
               session,  book_id ? book_id : "(null)");
        return;
    }

    /* If there's a begin method, call that. */
    if (session->backend->session_begin)
    {
        char *msg;
        QofBackendError err;

        (session->backend->session_begin)(session->backend, session,
                                          session->book_id, ignore_lock,
                                          create, force);
        PINFO("Done running session_begin on 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(" backend error %d %s", err, msg ? msg : "(null)");
            return;
        }
        if (msg != NULL)
        {
            PWARN("%s", msg);
            g_free(msg);
        }
    }

    LEAVE (" sess=%p book-id=%s",
           session,  book_id ? book_id : "(null)");
}
コード例 #10
0
ファイル: qofsession.c プロジェクト: kleopatra999/gnucash-2
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;
}
コード例 #11
0
ファイル: qofsession.c プロジェクト: kleopatra999/gnucash-2
void
qof_session_begin (QofSession *session, const char * book_id,
                   gboolean ignore_lock, gboolean create, gboolean force)
{
    gchar **splituri;

    if (!session) return;

    ENTER (" sess=%p ignore_lock=%d, book-id=%s",
           session, ignore_lock,
           book_id ? book_id : "(null)");

    /* Clear the error condition of previous errors */
    qof_session_clear_error (session);

    /* Check to see if this session is already open */
    if (session->book_id)
    {
        if (ERR_BACKEND_NO_ERR != qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_LOCKED, NULL);
        LEAVE("push error book is already open ");
        return;
    }

    /* seriously invalid */
    if (!book_id)
    {
        if (ERR_BACKEND_NO_ERR != qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
        LEAVE("push error missing book_id");
        return;
    }

    /* destroy the old backend */
    qof_session_destroy_backend(session);

    /* Store the session URL  */
    session->book_id = g_strdup (book_id);

    /* Look for something of the form of "file://", "http://" or
     * "postgres://". Everything before the colon is the access
     * method.  Load the first backend found for that access method.
     */
    splituri = g_strsplit ( book_id, "://", 2 );
    if ( splituri[1] == NULL ) /* no access method in the uri, use generic "file" backend */
        qof_session_load_backend(session, "file");
    else                       /* access method found, load appropriate backend */
        qof_session_load_backend(session, splituri[0]);
    g_strfreev ( splituri );

    /* No backend was found. That's bad. */
    if (NULL == session->backend)
    {
        g_free(session->book_id);
        session->book_id = NULL;
        if (ERR_BACKEND_NO_ERR == qof_session_get_error(session))
            qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
        LEAVE (" BAD: no backend: sess=%p book-id=%s",
               session,  book_id ? book_id : "(null)");
        return;
    }

    /* If there's a begin method, call that. */
    if (session->backend->session_begin)
    {
        char *msg;
        int err;

        (session->backend->session_begin)(session->backend, session,
                                          session->book_id, ignore_lock,
                                          create, force);
        PINFO("Done running session_begin on 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(" backend error %d %s", err, msg ? msg : "(null)");
            return;
        }
        if (msg != NULL)
        {
            PWARN("%s", msg);
            g_free(msg);
        }
    }

    LEAVE (" sess=%p book-id=%s",
           session,  book_id ? book_id : "(null)");
}