[libgda] Allow a virtual connection to be wrapped in a sub thread



commit 86b86f44c5b30d0cef260881538cddd3f3c41841
Author: Vivien Malerba <malerba gnome-db org>
Date:   Mon Oct 12 21:07:21 2009 +0200

    Allow a virtual connection to be wrapped in a sub thread
    
    added gda_virtual_connection_open_extended()

 doc/C/libgda-sections.txt                      |    1 +
 doc/C/tmpl/gda-virtual-connection.sgml         |   11 +++++
 libgda/gda-connection-internal.h               |    3 +-
 libgda/gda-connection.c                        |   14 ++++++-
 libgda/libgda.symbols                          |    1 +
 libgda/sqlite/virtual/gda-virtual-connection.c |   48 +++++++++++++++++++++++
 libgda/sqlite/virtual/gda-virtual-connection.h |    2 +
 libgda/thread-wrapper/Makefile.am              |    1 +
 libgda/thread-wrapper/gda-thread-provider.c    |   50 +++++++++++++++++++++++-
 libgda/thread-wrapper/gda-thread-provider.h    |    1 +
 10 files changed, 129 insertions(+), 3 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index 577cf54..3e591e7 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -560,6 +560,7 @@ gda_vprovider_hub_get_type
 <TITLE>GdaVirtualConnection</TITLE>
 GdaVirtualConnection
 gda_virtual_connection_open
+gda_virtual_connection_open_extended
 <SUBSECTION>
 gda_virtual_connection_internal_set_provider_data
 gda_virtual_connection_internal_get_provider_data
diff --git a/doc/C/tmpl/gda-virtual-connection.sgml b/doc/C/tmpl/gda-virtual-connection.sgml
index d896fe2..04f084a 100644
--- a/doc/C/tmpl/gda-virtual-connection.sgml
+++ b/doc/C/tmpl/gda-virtual-connection.sgml
@@ -33,6 +33,17 @@ This is a base virtual class for all virtual connection implementations
 @Returns: 
 
 
+<!-- ##### FUNCTION gda_virtual_connection_open_extended ##### -->
+<para>
+
+</para>
+
+ virtual_provider: 
+ options: 
+ error: 
+ Returns: 
+
+
 <!-- ##### FUNCTION gda_virtual_connection_internal_set_provider_data ##### -->
 <para>
 
diff --git a/libgda/gda-connection-internal.h b/libgda/gda-connection-internal.h
index 39a61bf..737eb5c 100644
--- a/libgda/gda-connection-internal.h
+++ b/libgda/gda-connection-internal.h
@@ -69,7 +69,8 @@ typedef struct {
 	/* current async. tasks */
 	GSList *async_tasks; /* list of ThreadConnectionAsyncTask pointers */
 } ThreadConnectionData; /* Per connection private data for */
-void           _gda_connection_force_transaction_status (GdaConnection *cnc, GdaConnection *wrapped_cnc);
+void               _gda_connection_force_transaction_status (GdaConnection *cnc, GdaConnection *wrapped_cnc);
+GdaServerProvider *_gda_connection_get_internal_thread_provider (void);
 
 G_END_DECLS
 
diff --git a/libgda/gda-connection.c b/libgda/gda-connection.c
index 69ba8bb..292a3d3 100644
--- a/libgda/gda-connection.c
+++ b/libgda/gda-connection.c
@@ -299,7 +299,7 @@ gda_connection_class_init (GdaConnectionClass *klass)
                                                               NULL,
                                                               (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (object_class, PROP_OPTIONS,
-                                         g_param_spec_flags ("options", NULL, _("Options (connection sharing)"),
+                                         g_param_spec_flags ("options", NULL, _("Options"),
 							    GDA_TYPE_CONNECTION_OPTIONS, GDA_CONNECTION_OPTIONS_NONE,
 							    (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (object_class, PROP_META_STORE,
@@ -822,6 +822,18 @@ cnc_task_free (CncTask *task)
 }
 
 /**
+ * _gda_connection_get_internal_thread_provider
+ */ 
+GdaServerProvider *
+_gda_connection_get_internal_thread_provider (void)
+{
+	if (!_gda_thread_wrapper_provider)
+		_gda_thread_wrapper_provider = GDA_SERVER_PROVIDER (g_object_new (GDA_TYPE_THREAD_PROVIDER, NULL));
+
+	return _gda_thread_wrapper_provider;
+}
+
+/**
  * gda_connection_open_from_dsn
  * @dsn: data source name.
  * @auth_string: authentication string, or %NULL
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index de4e514..dbb7c2a 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -882,6 +882,7 @@
 	gda_virtual_connection_internal_get_provider_data
 	gda_virtual_connection_internal_set_provider_data
 	gda_virtual_connection_open
+	gda_virtual_connection_open_extended
 	gda_virtual_provider_get_type
 	gda_vprovider_data_model_get_type
 	gda_vprovider_data_model_new
diff --git a/libgda/sqlite/virtual/gda-virtual-connection.c b/libgda/sqlite/virtual/gda-virtual-connection.c
index 138da71..5124636 100644
--- a/libgda/sqlite/virtual/gda-virtual-connection.c
+++ b/libgda/sqlite/virtual/gda-virtual-connection.c
@@ -26,6 +26,8 @@
 #include <sqlite3.h>
 #include "gda-virtual-connection.h"
 #include <gda-connection-private.h>
+#include <libgda/gda-connection-internal.h>
+#include <libgda/thread-wrapper/gda-thread-provider.h>
 
 #define PARENT_TYPE GDA_TYPE_CONNECTION
 #define CLASS(obj) (GDA_VIRTUAL_CONNECTION_CLASS (G_OBJECT_GET_CLASS (obj)))
@@ -153,6 +155,52 @@ gda_virtual_connection_open (GdaVirtualProvider *virtual_provider, GError **erro
 }
 
 /**
+ * gda_virtual_connection_open_extended
+ * @virtual_provider: a #GdaVirtualProvider object
+ * @options: a set of options to specify the new connection
+ * @error: a place to store errors, or %NULL
+ *
+ * Creates and opens a new virtual connection using the @virtual_provider provider. If @options
+ * contains the %GDA_CONNECTION_OPTIONS_THREAD_SAFE flag, then the returned connection will be
+ * a thread wrapped connection, and the actual (wrapped) virtual connection can be obtained through
+ * the "gda-virtual-connection" user property (use g_object_get_data() to get it).
+ *
+ * Returns: a new #GdaConnection object, or %NULL if an error occurred
+ */
+GdaConnection *
+gda_virtual_connection_open_extended (GdaVirtualProvider *virtual_provider, GdaConnectionOptions options, GError **error)
+{
+	GdaConnection *cnc = NULL;
+	g_return_val_if_fail (GDA_IS_VIRTUAL_PROVIDER (virtual_provider), NULL);
+
+	if (PROV_CLASS (virtual_provider)->create_connection) {
+		cnc = PROV_CLASS (virtual_provider)->create_connection ((GdaServerProvider*) virtual_provider);
+		if (cnc) {
+			g_object_set (G_OBJECT (cnc), "provider", virtual_provider, 
+				      "options", options & (~GDA_CONNECTION_OPTIONS_THREAD_SAFE), NULL);
+			if (!gda_connection_open (cnc, error)) {
+				g_object_unref (cnc);
+				cnc = NULL;
+			}
+		}
+	}
+	else
+		g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_ERROR, "%s", 
+			     _("Internal error: virtual provider does not implement the create_operation() virtual method"));
+
+	if (cnc && (options & GDA_CONNECTION_OPTIONS_THREAD_SAFE)) {
+		GdaConnection *wcnc;
+		wcnc = _gda_thread_provider_handle_virtual_connection (GDA_THREAD_PROVIDER (_gda_connection_get_internal_thread_provider ()),
+								       cnc);
+		g_object_set_data (G_OBJECT (wcnc), "gda-virtual-connection", cnc);
+		g_object_unref (cnc);
+		cnc = wcnc;
+	}
+
+	return cnc;
+}
+
+/**
  * gda_virtual_connection_internal_set_provider_data
  * @vcnc: a #GdaConnection object
  * @data: an opaque structure, known only to the provider for which @vcnc is opened
diff --git a/libgda/sqlite/virtual/gda-virtual-connection.h b/libgda/sqlite/virtual/gda-virtual-connection.h
index ddf847f..1f7e50c 100644
--- a/libgda/sqlite/virtual/gda-virtual-connection.h
+++ b/libgda/sqlite/virtual/gda-virtual-connection.h
@@ -55,6 +55,8 @@ struct _GdaVirtualConnectionClass {
 
 GType          gda_virtual_connection_get_type                   (void) G_GNUC_CONST;
 GdaConnection *gda_virtual_connection_open                       (GdaVirtualProvider *virtual_provider, GError **error);
+GdaConnection *gda_virtual_connection_open_extended              (GdaVirtualProvider *virtual_provider,
+								  GdaConnectionOptions options, GError **error);
 void           gda_virtual_connection_internal_set_provider_data (GdaVirtualConnection *vcnc, 
 								  gpointer data, GDestroyNotify destroy_func);
 gpointer       gda_virtual_connection_internal_get_provider_data (GdaVirtualConnection *cnc);
diff --git a/libgda/thread-wrapper/Makefile.am b/libgda/thread-wrapper/Makefile.am
index 6ca6725..6a4fb0b 100644
--- a/libgda/thread-wrapper/Makefile.am
+++ b/libgda/thread-wrapper/Makefile.am
@@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libgda_threadwrapper-4.0.la
 
 AM_CPPFLAGS = \
         -I$(top_srcdir) -I$(srcdir)/.. \
+	-I$(top_srcdir)/libgda/sqlite \
         -I$(top_builddir) \
         $(LIBGDA_CFLAGS) 
 
diff --git a/libgda/thread-wrapper/gda-thread-provider.c b/libgda/thread-wrapper/gda-thread-provider.c
index a8775c0..2bb15c6 100644
--- a/libgda/thread-wrapper/gda-thread-provider.c
+++ b/libgda/thread-wrapper/gda-thread-provider.c
@@ -36,6 +36,8 @@
 #include "gda-thread-meta.h"
 #include "gda-thread-wrapper.h"
 #include "gda-thread-recordset.h"
+#include <libgda/sqlite/virtual/gda-virtual-provider.h>
+#include <libgda/sqlite/virtual/gda-virtual-connection.h>
 
 #define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider)))
 
@@ -434,7 +436,7 @@ gda_thread_provider_open_connection (GdaServerProvider *provider, GdaConnection
 	ThreadConnectionData *cdata;
 	cdata = g_new0 (ThreadConnectionData, 1);
 	cdata->sub_connection = sub_cnc;
-	cdata->cnc_provider = data->out_cnc_provider;
+	cdata->cnc_provider = g_object_ref (data->out_cnc_provider);
 	cdata->wrapper = wr;
 	cdata->handlers_ids = g_array_sized_new (FALSE, FALSE, sizeof (gulong), 2);
 	g_free (data);
@@ -451,6 +453,49 @@ gda_thread_provider_open_connection (GdaServerProvider *provider, GdaConnection
 	return TRUE;
 }
 
+/**
+ * _gda_thread_provider_handle_virtual_connection
+ * @provider: a #GdaThreadProvider provider
+ * @sub_cnc: a #GdaConnection which has already been opened, normally a virtual connection
+ *
+ * Creates a new connection, wrapping @sub_cnc which has to be a virtual connection. @sub_cnc's
+ * reference count is incremented by this call.
+ *
+ * Returns: a new #GdaConnection, or %NULL if an error occurred.
+ */
+GdaConnection *
+_gda_thread_provider_handle_virtual_connection (GdaThreadProvider *provider, GdaConnection *sub_cnc)
+{
+	ThreadConnectionData *cdata;
+	GdaServerProvider *sub_prov;
+	GdaThreadWrapper *wr;
+	gboolean wr_created = FALSE;
+	GdaConnection *cnc;
+
+	g_return_val_if_fail (GDA_IS_THREAD_PROVIDER (provider), NULL);
+	g_return_val_if_fail (GDA_IS_VIRTUAL_CONNECTION (sub_cnc), NULL);
+
+	sub_prov = gda_connection_get_provider (sub_cnc);
+	g_return_val_if_fail (GDA_IS_VIRTUAL_PROVIDER (sub_prov), NULL);
+	wr = gda_thread_wrapper_new ();
+	if (!wr) {
+		g_warning (_("Multi threading is not supported or enabled"));
+		return NULL;
+	}
+
+	cnc = gda_thread_provider_create_connection (GDA_SERVER_PROVIDER (provider));
+
+	cdata = g_new0 (ThreadConnectionData, 1);
+	cdata->sub_connection = g_object_ref (sub_cnc);
+	cdata->cnc_provider = g_object_ref (sub_prov);
+	cdata->wrapper = wr;
+	cdata->handlers_ids = g_array_sized_new (FALSE, FALSE, sizeof (gulong), 2);
+	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_thread_free_cnc_data);
+	setup_signals (cnc, cdata);
+
+	return cnc;
+}
+
 static void
 sub_cnc_error_cb (GdaThreadWrapper *wrapper, GdaConnection *sub_cnc, const gchar *signal,
 		  gint n_param_values, const GValue *param_values,
@@ -1975,5 +2020,8 @@ gda_thread_free_cnc_data (ThreadConnectionData *cdata)
 		g_slist_foreach (cdata->async_tasks, (GFunc) _ThreadConnectionAsyncTask_free, NULL);
 		g_slist_free (cdata->async_tasks);
 	}
+
+	g_object_unref (cdata->cnc_provider);
+
 	g_free (cdata);
 }
diff --git a/libgda/thread-wrapper/gda-thread-provider.h b/libgda/thread-wrapper/gda-thread-provider.h
index fd857ef..7a680ba 100644
--- a/libgda/thread-wrapper/gda-thread-provider.h
+++ b/libgda/thread-wrapper/gda-thread-provider.h
@@ -51,6 +51,7 @@ struct _GdaThreadProviderClass {
 G_BEGIN_DECLS
 
 GType              _gda_thread_provider_get_type (void) G_GNUC_CONST;
+GdaConnection     *_gda_thread_provider_handle_virtual_connection (GdaThreadProvider *provider, GdaConnection *sub_cnc);
 
 G_END_DECLS
 



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