[libgda] Added GdaConnection::status-changed signal, and added gda_connection_get_status()



commit 7e60d7200b8892a383b13320529d3e6474edee0b
Author: Vivien Malerba <malerba gnome-db org>
Date:   Wed Apr 2 18:48:39 2014 +0200

    Added GdaConnection::status-changed signal, and added gda_connection_get_status()

 doc/C/Makefile.am                |    3 +-
 doc/C/connection-status.dia      |  Bin 0 -> 1626 bytes
 doc/C/connection-status.png      |  Bin 0 -> 4885 bytes
 doc/C/libgda-sections.txt        |    2 +
 libgda/gda-connection-internal.h |    4 +
 libgda/gda-connection.c          |  143 +++++++++++++++++++++++++++++++++++++-
 libgda/gda-connection.h          |   49 +++++++++-----
 libgda/gda-marshal.list          |    1 +
 libgda/gda-server-provider.c     |   72 +++++++++++++++----
 libgda/libgda.symbols            |    1 +
 libgda/test-cnc-open.c           |   26 ++++++-
 11 files changed, 263 insertions(+), 38 deletions(-)
---
diff --git a/doc/C/Makefile.am b/doc/C/Makefile.am
index 0320e7f..2d73f08 100644
--- a/doc/C/Makefile.am
+++ b/doc/C/Makefile.am
@@ -70,7 +70,8 @@ HTML_IMAGES = DataModels.png \
        SqlIdentifiers.png thread-wrapper.png \
        vi-basic-form.png vi-combo.png vi-data-entry.png \
        vi-login.png vi-cloud.png vi-provider-selector.png vi-raw-grid.png \
-       vi-info.png vi-filter.png vi-server-op.png vi-rte.png
+       vi-info.png vi-filter.png vi-server-op.png vi-rte.png \
+       connection-status.png
 
 # Extra options to supply to gtkdoc-fixref
 FIXXREF_OPTIONS=
diff --git a/doc/C/connection-status.dia b/doc/C/connection-status.dia
new file mode 100644
index 0000000..c42c341
Binary files /dev/null and b/doc/C/connection-status.dia differ
diff --git a/doc/C/connection-status.png b/doc/C/connection-status.png
new file mode 100644
index 0000000..41478ba
Binary files /dev/null and b/doc/C/connection-status.png differ
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index 5626022..05dd28f 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -105,6 +105,7 @@ gda_connection_event_get_type
 <FILE>gda-connection</FILE>
 <TITLE>GdaConnection</TITLE>
 GdaConnection
+GdaConnectionStatus
 GdaConnectionOptions
 GdaConnectionError
 GDA_CONNECTION_ERROR
@@ -116,6 +117,7 @@ gda_connection_open_async
 gda_connection_close
 gda_connection_close_no_warning
 gda_connection_is_opened
+gda_connection_get_status
 <SUBSECTION>
 gda_connection_set_main_context
 gda_connection_get_main_context
diff --git a/libgda/gda-connection-internal.h b/libgda/gda-connection-internal.h
index 9fe1016..a7e0859 100644
--- a/libgda/gda-connection-internal.h
+++ b/libgda/gda-connection-internal.h
@@ -47,6 +47,10 @@ gboolean           _gda_connection_close_no_warning (GdaConnection *cnc, GError
 GdaWorker         *_gda_connection_get_worker (GdaConnection *cnc);
 guint              _gda_connection_get_exec_slowdown (GdaConnection *cnc);
 
+void               _gda_connection_status_start_batch (GdaConnection *cnc, GdaConnectionStatus status);
+void               _gda_connection_status_stop_batch (GdaConnection *cnc);
+void               _gda_connection_set_status (GdaConnection *cnc, GdaConnectionStatus status);
+
 /*
  * Opens a connection to an SQLite database. This function is intended to be used
  * internally when objects require an SQLite connection, for example for the GdaMetaStore
diff --git a/libgda/gda-connection.c b/libgda/gda-connection.c
index fc54bd8..8096166 100644
--- a/libgda/gda-connection.c
+++ b/libgda/gda-connection.c
@@ -101,6 +101,9 @@ struct _GdaConnectionPrivate {
        gint                  events_array_next;
        GList                *events_list; /* for API compat */
 
+       GdaConnectionStatus   status;
+       guint                 batch_status;
+
        GdaTransactionStatus *trans_status;
        GHashTable           *prepared_stmts;
 
@@ -149,10 +152,11 @@ enum {
         CONN_CLOSED,
        DSN_CHANGED,
        TRANSACTION_STATUS_CHANGED,
+       STATUS_CHANGED,
        LAST_SIGNAL
 };
 
-static gint gda_connection_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0, 0 };
+static gint gda_connection_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0, 0, 0 };
 
 /* properties */
 enum
@@ -298,6 +302,25 @@ gda_connection_class_init (GdaConnectionClass *klass)
                              g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
 
+       /**
+        * GdaConnection::status-changed:
+        * @cnc: the #GdaConnection
+        * @status: the new connection status
+        *
+        * Gets emitted when the @cnc's status has changed (usually when a the connection is being used to 
execute
+        * a statement)
+        *
+        * Since: 6.0
+        */
+       gda_connection_signals[STATUS_CHANGED] =
+               g_signal_new ("status-changed",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GdaConnectionClass, status_changed),
+                             NULL, NULL,
+                             _gda_marshal_VOID__ENUM,
+                             G_TYPE_NONE, 1, GDA_TYPE_CONNECTION_STATUS);
+
        /* Properties */
         object_class->set_property = gda_connection_set_property;
         object_class->get_property = gda_connection_get_property;
@@ -436,6 +459,8 @@ gda_connection_init (GdaConnection *cnc, G_GNUC_UNUSED GdaConnectionClass *klass
        cnc->priv->events_array = g_new0 (GdaConnectionEvent*, EVENTS_ARRAY_SIZE);
        cnc->priv->events_array_full = FALSE;
        cnc->priv->events_array_next = 0;
+       cnc->priv->status = GDA_CONNECTION_STATUS_CLOSED;
+       cnc->priv->batch_status = 0;
        cnc->priv->trans_status = NULL; /* no transaction yet */
        cnc->priv->prepared_stmts = NULL;
 
@@ -777,8 +802,10 @@ gda_connection_get_property (GObject *object,
  * @context: (allow-none): a #GMainContext, or %NULL
  *
  * Defines the #GMainContext which will still process events while a potentially blocking operation is 
performed.
+ *
  * For exemple if there is a GUI which needs to continue to handle events, then you can use this function to 
pass
  * the default #GMainContext used for the UI refreshing, for example:
+ *
  * <programlisting><![CDATA[GMainContext *context;
  * cnc = gda_connection_new_...;
  * context = g_main_context_ref_thread_default ();
@@ -789,7 +816,8 @@ gda_connection_get_property (GObject *object,
  *     ...
  * ]]></programlisting>
  *
- * If @context is %NULL, then potentially blocking operation will actually block any event from being 
processed.
+ * If @context is %NULL, then potentially blocking operation will actually block any event from being 
processed
+ * while the blocking operation is being performed.
  *
  * Since: 6.0
  */
@@ -1565,6 +1593,117 @@ _gda_connection_get_exec_slowdown (GdaConnection *cnc)
        return cnc->priv->exec_slowdown;
 }
 
+static void
+assert_status_transaction (GdaConnectionStatus old, GdaConnectionStatus new)
+{
+       if (old == new)
+               return;
+       switch (old) {
+       case GDA_CONNECTION_STATUS_CLOSED:
+               g_assert (new == GDA_CONNECTION_STATUS_OPENING);
+               break;
+       case GDA_CONNECTION_STATUS_OPENING:
+               g_assert ((new == GDA_CONNECTION_STATUS_IDLE) || (new == GDA_CONNECTION_STATUS_CLOSED));
+               break;
+       case GDA_CONNECTION_STATUS_IDLE:
+               g_assert ((new == GDA_CONNECTION_STATUS_BUSY) || (new == GDA_CONNECTION_STATUS_CLOSED));
+               break;
+       case GDA_CONNECTION_STATUS_BUSY:
+               g_assert ((new == GDA_CONNECTION_STATUS_IDLE) || (new == GDA_CONNECTION_STATUS_CLOSED));
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
+/*
+ * _gda_connection_set_status:
+ *
+ * Set @cnc's new status, may emit the "status-changed" signal along the way
+ *
+ * WARNING: @cnc _MUST_ be locked before this function is called
+ */
+void
+_gda_connection_set_status (GdaConnection *cnc, GdaConnectionStatus status)
+{
+       if (!cnc || (status == cnc->priv->status))
+               return;
+
+       if ((cnc->priv->batch_status > 0) &&
+           (status != GDA_CONNECTION_STATUS_CLOSED))
+               return;
+
+       assert_status_transaction (cnc->priv->status, status);
+       cnc->priv->batch_status = 0;
+       cnc->priv->status = status;
+       g_signal_emit (G_OBJECT (cnc), gda_connection_signals[STATUS_CHANGED], 0, status);
+       if (status == GDA_CONNECTION_STATUS_CLOSED)
+               g_signal_emit (G_OBJECT (cnc), gda_connection_signals[CONN_CLOSED], 0, status);
+}
+
+/*
+ * _gda_connection_status_start_batch:
+ *
+ * This function ensures that the connection's status is set and remains to @status, except for the CLOSED
+ * status.
+ *
+ * To cancel the effect, use _gda_connection_status_stop_batch().
+ */
+void
+_gda_connection_status_start_batch (GdaConnection *cnc, GdaConnectionStatus status)
+{
+       cnc->priv->batch_status++;
+       if (cnc->priv->status != status) {
+               assert_status_transaction (cnc->priv->status, status);
+               cnc->priv->status = status;
+               g_signal_emit (G_OBJECT (cnc), gda_connection_signals[STATUS_CHANGED], 0, status);
+       }
+}
+
+/*
+ * _gda_connection_status_stop_batch:
+ *
+ * See _gda_connection_status_start_batch().
+ *
+ * This functions ensures that the connections's status is IDLE.
+ */
+void
+_gda_connection_status_stop_batch (GdaConnection *cnc)
+{
+       if (cnc->priv->batch_status == 0)
+               return;
+
+       cnc->priv->batch_status --;
+       if (cnc->priv->status != GDA_CONNECTION_STATUS_IDLE) {
+               assert_status_transaction (cnc->priv->status, GDA_CONNECTION_STATUS_IDLE);
+               cnc->priv->status = GDA_CONNECTION_STATUS_IDLE;
+               g_signal_emit (G_OBJECT (cnc), gda_connection_signals[STATUS_CHANGED], 0, 
GDA_CONNECTION_STATUS_IDLE);
+       }
+}
+
+
+/**
+ * gda_connection_get_status:
+ * @cnc: a #GdaConnection
+ *
+ * Get the current status of @cnc. Note that this function needs to lock the connection (see #GdaLockable)
+ * to obtain the result.
+ *
+ * Returns: the connection's status
+ *
+ * Since: 6.0
+ */
+GdaConnectionStatus
+gda_connection_get_status (GdaConnection *cnc)
+{
+       g_return_val_if_fail (GDA_IS_CONNECTION (cnc), GDA_CONNECTION_STATUS_CLOSED);
+       GdaConnectionStatus status;
+       gda_connection_lock ((GdaLockable*) cnc);
+       status = cnc->priv->status;
+       gda_connection_unlock ((GdaLockable*) cnc);
+       return status;
+}
+
 /**
  * gda_connection_is_opened:
  * @cnc: a #GdaConnection object.
diff --git a/libgda/gda-connection.h b/libgda/gda-connection.h
index 34fcab9..dc0eb6f 100644
--- a/libgda/gda-connection.h
+++ b/libgda/gda-connection.h
@@ -85,23 +85,10 @@ typedef enum {
  * By default these functions will block, unless you speficy a #GMainContext from which events will be 
processed
  * while opening the connection using gda_connection_set_main_context().
  *
- * Use the connection object to execute statements, use transactions, get meta data information, ...
- *
- * If supported by the database provider being used, statements can be executed asynchronously instead of
- * blocking the execution thread untill the execution of a statement is finished. Each database provider
- * is free to implement this feature as it wishes (using the API or using threads). The steps involved to
- * execute a statement are then:
- * <itemizedlist>
- *   <listitem><para>Request the statement execution using
- *     <link linkend="gda-connection-async-statement-execute">gda_connection_async_statement_execute() which 
returns an
- *       execution ID to be used to identify a specific request</link></para></listitem>
- *   <listitem><para>Do some useful things (that is why async. statements' excution are 
for)</para></listitem>
- *   <listitem><para>Use one or more times 
- *     <link linkend="gda-connection-async-fetch-result">gda_connection_async_fetch_result()</link> to see
- *     if the execution is finished, using the request ID</para></listitem>
- *   <listitem><para>Use <link linkend="gda-connection-async-cancel">gda_connection_async_cancel()</link> to 
cancel
- * the execution of a statement</para></listitem>
- * </itemizedlist>
+ * The same gda_connection_set_main_context() allows the program to still handle events while a
+ * potentially blocking operation (such as executing a statement) is being carried out (this is a change 
compared to the
+ * #GdaConnection object in Libgda versions before 6.x, where asynchronous execution was featured
+ * using a set of specific functions like gda_connection_async_statement_execute()).
  *
  * The #GdaConnection object implements its own locking mechanism so it is thread-safe. If a #GMainContext 
has been
  * specified using gda_connection_set_main_context(), then the events will continue to be processed while the
@@ -113,10 +100,36 @@ struct _GdaConnection {
        GdaConnectionPrivate *priv;
 };
 
+/**
+ * GdaConnectionStatus:
+ * @GDA_CONNECTION_STATUS_CLOSED: the connection is closed (default status upon creation)
+ * @GDA_CONNECTION_STATUS_OPENING: the connection is currently being opened
+ * @GDA_CONNECTION_STATUS_IDLE: the connection is opened but not currently used
+ * @GDA_CONNECTION_STATUS_BUSY: the connection is opened and currently being used
+ *
+ * Indicates the current status of a connection. The possible status and the transitions between those status
+ * are indicated in the diagram below:
+ *  <mediaobject>
+ *    <imageobject role="html">
+ *      <imagedata fileref="connection-status.png" format="PNG" contentwidth="50mm"/>
+ *    </imageobject>
+ *    <textobject>
+ *      <phrase>GdaConnection's status and transitions between different status</phrase>
+ *    </textobject>
+ *  </mediaobject>
+ */
+typedef enum {
+       GDA_CONNECTION_STATUS_CLOSED,
+       GDA_CONNECTION_STATUS_OPENING,
+       GDA_CONNECTION_STATUS_IDLE,
+       GDA_CONNECTION_STATUS_BUSY
+} GdaConnectionStatus;
+
 struct _GdaConnectionClass {
        GObjectClass          object_class;
 
        /* signals */
+       void   (*status_changed)            (GdaConnection *obj, GdaConnectionStatus status);
        void   (*error)                     (GdaConnection *cnc, GdaConnectionEvent *error);
         void   (*conn_opened)               (GdaConnection *obj);
         void   (*conn_to_close)             (GdaConnection *obj);
@@ -124,6 +137,7 @@ struct _GdaConnectionClass {
        void   (*dsn_changed)               (GdaConnection *obj);
        void   (*transaction_status_changed)(GdaConnection *obj);
 
+
        /*< private >*/
        /* Padding for future expansion */
        void (*_gda_reserved1) (void);
@@ -267,6 +281,7 @@ guint                gda_connection_open_async           (GdaConnection *cnc, Gd
 
 gboolean             gda_connection_close                (GdaConnection *cnc, GError **error);
 gboolean             gda_connection_is_opened            (GdaConnection *cnc);
+GdaConnectionStatus  gda_connection_get_status           (GdaConnection *cnc);
 
 GdaConnectionOptions gda_connection_get_options          (GdaConnection *cnc);
 
diff --git a/libgda/gda-marshal.list b/libgda/gda-marshal.list
index 8ecaba3..a02ab50 100644
--- a/libgda/gda-marshal.list
+++ b/libgda/gda-marshal.list
@@ -39,3 +39,4 @@ VOID:INT,BOOLEAN
 VOID:STRING,INT
 POINTER:POINTER
 BOOLEAN:POINTER
+VOID:ENUM
diff --git a/libgda/gda-server-provider.c b/libgda/gda-server-provider.c
index c03f76b..e4636f7 100644
--- a/libgda/gda-server-provider.c
+++ b/libgda/gda-server-provider.c
@@ -2011,7 +2011,7 @@ worker_open_connection (WorkerOpenConnectionData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay);
+               g_print (_("Delaying opening connection for %u ms\n"), delay);
                g_usleep (delay);
        }
 
@@ -2075,15 +2075,11 @@ stage2_open_connection (GdaWorker *worker, GdaConnection *cnc, gpointer result)
                if (!cdata) {
                        g_warning ("Internal error: connection reported as opened, yet no provider data set");
                        result = NULL;
+                       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_CLOSED);
                }
                else {
-#ifdef GDA_DEBUG_signal
-                       g_print (">> 'CONN_OPENED' from %s\n", __FUNCTION__);
-#endif
                        g_signal_emit_by_name (G_OBJECT (cnc), "conn-opened");
-#ifdef GDA_DEBUG_signal
-                       g_print ("<< 'CONN_OPENED' from %s\n", __FUNCTION__);
-#endif
+                       _gda_connection_status_stop_batch (cnc);
                }
        }
 
@@ -2140,6 +2136,7 @@ _gda_server_provider_open_connection (GdaServerProvider *provider, GdaConnection
        }
 
        gda_lockable_lock ((GdaLockable*) cnc); /* CNC LOCK */
+       _gda_connection_status_start_batch (cnc, GDA_CONNECTION_STATUS_OPENING);
 
        GdaWorker *worker;
        worker = _gda_server_provider_create_worker (provider, TRUE);
@@ -2149,6 +2146,7 @@ _gda_server_provider_open_connection (GdaServerProvider *provider, GdaConnection
        if (cb_func) {
                if (!gda_worker_set_callback (worker, context,
                                              (GdaWorkerCallback) server_provider_job_done_callback, 
provider, error)) {
+                       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_CLOSED);
                        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
                        gda_worker_unref (worker);
                        return FALSE;
@@ -2176,6 +2174,7 @@ _gda_server_provider_open_connection (GdaServerProvider *provider, GdaConnection
                                                (GdaWorkerFunc) worker_open_connection,
                                                jdata, NULL, NULL, error);
                if (job_id == 0) {
+                       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_CLOSED);
                        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
                        WorkerOpenConnectionData_free (jdata);
                        return FALSE; /* error */
@@ -2244,7 +2243,7 @@ worker_close_connection (WorkerCloseConnectionData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay / 1000);
+               g_print (_("Delaying closing connection for %u ms\n"), delay / 1000);
                g_usleep (delay);
        }
 
@@ -2281,9 +2280,12 @@ stage2_close_connection (GdaConnection *cnc, gpointer result)
                        if (cdata->provider_data_destroy_func)
                                cdata->provider_data_destroy_func (cdata);
                }
-
-               g_signal_emit_by_name (G_OBJECT (cnc), "conn-closed");
+               _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_CLOSED);
        }
+       else
+               _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
+
+       gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        return result ? TRUE : FALSE;
 }
@@ -2303,9 +2305,12 @@ _gda_server_provider_close_connection (GdaServerProvider *provider, GdaConnectio
        g_return_val_if_fail (cnc && (gda_connection_get_provider (cnc) == provider), FALSE);
        g_return_val_if_fail (gda_connection_is_opened (cnc), TRUE);
 
+       gda_lockable_lock ((GdaLockable*) cnc); /* CNC LOCK */
+
        GdaServerProviderConnectionData *cdata;
        cdata = gda_connection_internal_get_provider_data_error (cnc, NULL);
        if (!cdata) {
+               gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
                g_warning ("Internal error: connection reported as opened, yet no provider data set");
                return FALSE;
        }
@@ -2319,6 +2324,7 @@ _gda_server_provider_close_connection (GdaServerProvider *provider, GdaConnectio
        jdata->provider = provider;
        jdata->cnc = g_object_ref (cnc);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer result;
        gda_worker_do_job (cdata->worker, context, 0, &result, NULL,
                           (GdaWorkerFunc) worker_close_connection, jdata, (GDestroyNotify) 
WorkerCloseConnectionData_free,
@@ -2394,11 +2400,13 @@ _gda_server_provider_statement_prepare (GdaServerProvider *provider, GdaConnecti
        data.cnc = cnc;
        data.stmt = stmt;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_statement_prepare, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -2434,7 +2442,7 @@ worker_statement_execute (WorkerExecuteStatementData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay / 1000);
+               g_print (_("Delaying statement execution for %u ms\n"), delay / 1000);
                g_usleep (delay);
        }
 
@@ -2498,11 +2506,13 @@ _gda_server_provider_statement_execute (GdaServerProvider *provider, GdaConnecti
        data.col_types = col_types;
        data.last_inserted_row = last_inserted_row;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
-                          (GdaWorkerFunc) worker_statement_execute, (gpointer) &data, NULL, NULL, NULL);
+                          (GdaWorkerFunc) worker_statement_execute, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -2583,11 +2593,13 @@ _gda_server_provider_statement_to_sql  (GdaServerProvider *provider, GdaConnecti
        data.flags = flags;
        data.params_used = params_used;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_stmt_to_sql, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -2660,11 +2672,13 @@ _gda_server_provider_identifier_quote (GdaServerProvider *provider, GdaConnectio
        data.for_meta_store = for_meta_store;
        data.force_quotes = force_quotes;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_identifier_quote, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -2883,11 +2897,13 @@ _gda_server_provider_meta_0arg (GdaServerProvider *provider, GdaConnection *cnc,
        data.values[2] = NULL;
        data.values[3] = NULL;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_meta, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -2941,11 +2957,13 @@ _gda_server_provider_meta_1arg (GdaServerProvider *provider, GdaConnection *cnc,
        data.values[2] = NULL;
        data.values[3] = NULL;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_meta, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -2999,11 +3017,13 @@ _gda_server_provider_meta_2arg (GdaServerProvider *provider, GdaConnection *cnc,
        data.values[2] = NULL;
        data.values[3] = NULL;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_meta, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -3058,11 +3078,13 @@ _gda_server_provider_meta_3arg (GdaServerProvider *provider, GdaConnection *cnc,
        data.values[2] = value2;
        data.values[3] = NULL;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_meta, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -3117,11 +3139,13 @@ _gda_server_provider_meta_4arg (GdaServerProvider *provider, GdaConnection *cnc,
        data.values[2] = value2;
        data.values[3] = value3;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_meta, (gpointer) &data, NULL, NULL, NULL);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        if (cnc)
                gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
@@ -3155,7 +3179,7 @@ worker_begin_transaction (WorkerTransactionData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay / 1000);
+               g_print (_("Delaying transaction for %u ms\n"), delay / 1000);
                g_usleep (delay);
        }
 
@@ -3201,11 +3225,13 @@ _gda_server_provider_begin_transaction (GdaServerProvider *provider, GdaConnecti
        data.name = name;
        data.level = level;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_begin_transaction, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3222,7 +3248,7 @@ worker_commit_transaction (WorkerTransactionData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay / 1000);
+               g_print (_("Delaying transaction for %u ms\n"), delay / 1000);
                g_usleep (delay);
        }
 
@@ -3267,11 +3293,13 @@ _gda_server_provider_commit_transaction (GdaServerProvider *provider, GdaConnect
        data.cnc = cnc;
        data.name = name;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_commit_transaction, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3288,7 +3316,7 @@ worker_rollback_transaction (WorkerTransactionData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay / 1000);
+               g_print (_("Delaying transaction for %u ms\n"), delay / 1000);
                g_usleep (delay);
        }
 
@@ -3333,11 +3361,13 @@ _gda_server_provider_rollback_transaction (GdaServerProvider *provider, GdaConne
        data.cnc = cnc;
        data.name = name;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_rollback_transaction, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3391,11 +3421,13 @@ _gda_server_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *
        data.cnc = cnc;
        data.name = name;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_add_savepoint, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3449,11 +3481,13 @@ _gda_server_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnect
        data.cnc = cnc;
        data.name = name;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_rollback_savepoint, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3507,11 +3541,13 @@ _gda_server_provider_delete_savepoint (GdaServerProvider *provider, GdaConnectio
        data.cnc = cnc;
        data.name = name;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_delete_savepoint, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3547,7 +3583,7 @@ worker_xa (WorkerXAData *data, GError **error)
        guint delay;
        delay = _gda_connection_get_exec_slowdown (data->cnc);
        if (delay > 0) {
-               g_print ("Delaying execution for %u ms\n", delay / 1000);
+               g_print (_("Delaying distributed transaction for %u ms\n"), delay / 1000);
                g_usleep (delay);
        }
 
@@ -3655,11 +3691,13 @@ _gda_server_provider_xa (GdaServerProvider *provider, GdaConnection *cnc, const
        data.trx = trx;
        data.type = type;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_xa, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
@@ -3697,11 +3735,13 @@ _gda_server_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc
        data.trx = NULL;
        data.type = GDA_XA_RECOVER;
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_BUSY);
        gpointer retval;
        gda_worker_do_job (worker, context, 0, &retval, NULL,
                           (GdaWorkerFunc) worker_xa, (gpointer) &data, NULL, NULL, error);
        g_main_context_unref (context);
 
+       _gda_connection_set_status (cnc, GDA_CONNECTION_STATUS_IDLE);
        gda_lockable_unlock ((GdaLockable*) cnc); /* CNC UNLOCK */
 
        gda_worker_unref (worker);
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index e6ef9f5..1d70da2 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -131,6 +131,7 @@
        gda_connection_get_prepared_statement
        gda_connection_get_provider
        gda_connection_get_provider_name
+       gda_connection_get_status
        gda_connection_get_transaction_status
        gda_connection_get_type
        gda_connection_insert_row_into_table
diff --git a/libgda/test-cnc-open.c b/libgda/test-cnc-open.c
index c3b083a..d4adae5 100644
--- a/libgda/test-cnc-open.c
+++ b/libgda/test-cnc-open.c
@@ -25,7 +25,6 @@ static guint test3 (void);
 static guint test4 (void);
 static guint test5 (void);
 
-
 int main(int argc, const char *argv[])
 {
        gda_init ();
@@ -267,8 +266,22 @@ test4 (void)
        return opened ? 1 : 0;
 }
 
+static void
+t5_status_changed_cb (GdaConnection *cnc, GdaConnectionStatus status, guint *nsignals)
+{
+       gchar *status_str[] = {
+               "CLOSED",
+               "OPENING",
+               "IDLE",
+               "BUSY",
+               "CLOSING"
+       };
+       g_print ("Cnc status changed to %s\n", status_str [status]);
+       (*nsignals) ++;
+}
+
 /*
- * Test 5: open, close and open again
+ * Test 5: open, close and open again, also tests signal's emission
  */
 static guint
 test5 (void)
@@ -284,6 +297,10 @@ test5 (void)
                return 1;
        }
 
+       guint nsignals = 0;
+       g_signal_connect (cnc, "status-changed",
+                         G_CALLBACK (t5_status_changed_cb), &nsignals);
+
        guint counter = 0;
        setup_main_context (cnc, &counter);
 
@@ -327,5 +344,10 @@ test5 (void)
 
        g_object_unref (cnc);
 
+       if (nsignals != 8) {
+               g_print ("Expected %d signals and got %d\n", 8, nsignals);
+               return 1;
+       }
+
        return 0;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]