[tracker/async-queries] libtracker-db: Add TrackerDBInterfacePool.
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/async-queries] libtracker-db: Add TrackerDBInterfacePool.
- Date: Tue, 13 Apr 2010 13:23:20 +0000 (UTC)
commit ba157f975d9c9b5c082efe383c0d2cfb39c45ab6
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Apr 13 14:57:58 2010 +0200
libtracker-db: Add TrackerDBInterfacePool.
TrackerDBInterfacePool allows threaded execution of select queries, so shorter queries don't
starve and misbehaving queries may be cancelled.
src/libtracker-db/tracker-db-manager.c | 271 ++++++++++++++++++++++++++++++++
src/libtracker-db/tracker-db-manager.h | 36 +++++
2 files changed, 307 insertions(+), 0 deletions(-)
---
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index b39efdb..41c86fc 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -142,6 +142,24 @@ static TrackerDBDefinition dbs[] = {
0 },
};
+
+typedef struct TrackerDBInterfacePoolPrivate TrackerDBInterfacePoolPrivate;
+typedef struct PoolJob PoolJob;
+
+struct TrackerDBInterfacePoolPrivate {
+ GThreadPool *interface_pool;
+};
+
+struct PoolJob {
+ guint priority;
+ GSimpleAsyncResult *async_result;
+ GCancellable *cancellable;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ gchar *query;
+ GValueArray *bind_values;
+};
+
static gboolean db_exec_no_reply (TrackerDBInterface *iface,
const gchar *query,
...);
@@ -159,6 +177,11 @@ static gpointer db_type_enum_class_pointer;
static TrackerDBInterface *resources_iface;
static TrackerDBManagerFlags old_flags = 0;
+#define TRACKER_DB_INTERFACE_POOL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_DB_INTERFACE_POOL, TrackerDBInterfacePoolPrivate))
+
+G_DEFINE_TYPE (TrackerDBInterfacePool, tracker_db_interface_pool, G_TYPE_OBJECT)
+
+
static const gchar *
location_to_directory (TrackerDBLocation location)
{
@@ -1203,3 +1226,251 @@ tracker_db_manager_has_enough_space (void)
{
return tracker_file_system_has_enough_space (data_dir, TRACKER_DB_MIN_REQUIRED_SPACE, FALSE);
}
+
+static void
+tracker_db_interface_pool_finalize (GObject *object)
+{
+ TrackerDBInterfacePoolPrivate *priv;
+
+ priv = TRACKER_DB_INTERFACE_POOL_GET_PRIVATE (object);
+
+ G_OBJECT_CLASS (tracker_db_interface_pool_parent_class)->finalize (object);
+}
+
+static void
+tracker_db_interface_pool_class_init (TrackerDBInterfacePoolClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_db_interface_pool_finalize;
+
+ g_type_class_add_private (object_class,
+ sizeof (TrackerDBInterfacePoolPrivate));
+}
+
+static void
+pool_job_destroy (PoolJob *job)
+{
+ if (job->cancellable) {
+ g_object_unref (job->cancellable);
+ }
+
+ if (job->bind_values) {
+ g_value_array_free (job->bind_values);
+ }
+
+ g_object_unref (job->async_result);
+ g_free (job->query);
+
+ g_slice_free (PoolJob, job);
+}
+
+static void
+interface_pool_dispatch_cb (gpointer data,
+ gpointer user_data)
+{
+ static GStaticPrivate interface_data_key = G_STATIC_PRIVATE_INIT;
+ TrackerDBInterface *interface;
+ TrackerDBStatement *statement;
+ TrackerDBCursor *cursor;
+ GError *error = NULL;
+ PoolJob *job;
+ gint i, n_bind_values;
+
+ interface = g_static_private_get (&interface_data_key);
+ job = data;
+
+ if (job->cancellable) {
+ g_cancellable_push_current (job->cancellable);
+ }
+
+ /* Ensure the interface is there */
+ if (!interface) {
+ interface = tracker_db_manager_get_db_interfaces (3,
+ TRACKER_DB_METADATA,
+ TRACKER_DB_FULLTEXT,
+ TRACKER_DB_CONTENTS);
+
+ g_static_private_set (&interface_data_key,
+ interface,
+ (GDestroyNotify) g_object_unref);
+ }
+
+ statement = tracker_db_interface_create_statement (interface, "%s", job->query);
+
+ if (job->bind_values) {
+ n_bind_values = job->bind_values->n_values;
+ } else {
+ n_bind_values = 0;
+ }
+
+ for (i = 0; i < n_bind_values; i++) {
+ GType type;
+ GValue *val;
+
+ val = g_value_array_get_nth (job->bind_values, i);
+ type = G_VALUE_TYPE (val);
+
+ if (type == G_TYPE_STRING) {
+ tracker_db_statement_bind_text (statement, i,
+ g_value_get_string (val));
+ } else if (type == G_TYPE_DOUBLE) {
+ tracker_db_statement_bind_double (statement, i,
+ g_value_get_double (val));
+ } else if (type == G_TYPE_INT) {
+ tracker_db_statement_bind_int (statement, i,
+ g_value_get_int (val));
+ } else if (type == G_TYPE_INT64) {
+ tracker_db_statement_bind_int64 (statement, i,
+ g_value_get_int64 (val));
+ } else {
+ tracker_db_statement_bind_null (statement, i);
+ }
+ }
+
+ cursor = tracker_db_statement_start_cursor (statement, &error);
+
+ if (error) {
+ g_simple_async_result_set_from_error (G_SIMPLE_ASYNC_RESULT (job->async_result), error);
+ g_error_free (error);
+ } else {
+ TrackerDBResultSet *result_set;
+ guint n_columns;
+
+ n_columns = tracker_db_cursor_get_n_columns (cursor);
+ result_set = _tracker_db_result_set_new (n_columns);
+
+ do {
+ GValue val = { 0 };
+
+ _tracker_db_result_set_append (result_set);
+
+ for (i = 0; i < n_columns; i++) {
+ tracker_db_cursor_get_value (cursor, i, &val);
+
+ if (G_IS_VALUE (&val)) {
+ _tracker_db_result_set_set_value (result_set, i, &val);
+ g_value_unset (&val);
+ }
+
+ if (job->cancellable &&
+ g_cancellable_is_cancelled (job->cancellable)) {
+ break;
+ }
+ }
+
+ if (job->cancellable &&
+ g_cancellable_is_cancelled (job->cancellable)) {
+ break;
+ }
+ } while (tracker_db_cursor_iter_next (cursor));
+
+ g_object_unref (cursor);
+
+ if (job->cancellable &&
+ g_cancellable_set_error_if_cancelled (job->cancellable, &error)) {
+ g_simple_async_result_set_from_error (G_SIMPLE_ASYNC_RESULT (job->async_result), error);
+ g_error_free (error);
+ } else {
+ g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (job->async_result),
+ result_set, (GDestroyNotify) g_object_unref);
+ }
+ }
+
+ g_object_unref (statement);
+
+ g_simple_async_result_complete_in_idle (G_SIMPLE_ASYNC_RESULT (job->async_result));
+
+ if (job->cancellable) {
+ g_cancellable_pop_current (job->cancellable);
+ }
+
+ pool_job_destroy (job);
+}
+
+static void
+tracker_db_interface_pool_init (TrackerDBInterfacePool *pool)
+{
+ TrackerDBInterfacePoolPrivate *priv;
+
+ priv = TRACKER_DB_INTERFACE_POOL_GET_PRIVATE (pool);
+
+ priv->interface_pool = g_thread_pool_new (interface_pool_dispatch_cb,
+ NULL, 10,
+ FALSE, NULL);
+}
+
+TrackerDBInterfacePool *
+tracker_db_interface_pool_new (void)
+{
+ return g_object_new (TRACKER_TYPE_DB_INTERFACE_POOL, NULL);
+}
+
+TrackerDBResultSet *
+tracker_db_interface_pool_execute_query_finish (TrackerDBInterfacePool *pool,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *result;
+ TrackerDBResultSet *result_set;
+
+ g_return_val_if_fail (TRACKER_IS_DB_INTERFACE_POOL (pool), NULL);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), NULL);
+
+ result = G_SIMPLE_ASYNC_RESULT (res);
+
+ if (g_simple_async_result_propagate_error (result, error)) {
+ return NULL;
+ }
+
+ result_set = TRACKER_DB_RESULT_SET (g_simple_async_result_get_op_res_gpointer (result));
+
+ return g_object_ref (result_set);
+}
+
+void
+tracker_db_interface_pool_execute_query_async (TrackerDBInterfacePool *pool,
+ guint priority,
+ const gchar *query,
+ GValueArray *bind_values,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TrackerDBInterfacePoolPrivate *priv;
+ GError *error = NULL;
+ PoolJob *job;
+
+ g_return_if_fail (TRACKER_IS_DB_INTERFACE_POOL (pool));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (query != NULL);
+
+ priv = TRACKER_DB_INTERFACE_POOL_GET_PRIVATE (pool);
+
+ job = g_slice_new0 (PoolJob);
+
+ job->async_result = g_simple_async_result_new (G_OBJECT (pool), callback, user_data,
+ tracker_db_interface_pool_execute_query_async);
+ g_simple_async_result_set_handle_cancellation (job->async_result, TRUE);
+
+ job->priority = priority;
+ job->callback = callback;
+ job->user_data = user_data;
+ job->query = g_strdup (query);
+
+ if (bind_values) {
+ job->bind_values = g_value_array_copy (bind_values);
+ }
+
+ if (cancellable) {
+ job->cancellable = g_object_ref (cancellable);
+ }
+
+ g_thread_pool_push (priv->interface_pool, job, &error);
+
+ if (error) {
+ g_simple_async_report_gerror_in_idle (G_OBJECT (pool), callback, user_data, error);
+ g_error_free (error);
+ pool_job_destroy (job);
+ }
+}
diff --git a/src/libtracker-db/tracker-db-manager.h b/src/libtracker-db/tracker-db-manager.h
index 34375d4..5cf1743 100644
--- a/src/libtracker-db/tracker-db-manager.h
+++ b/src/libtracker-db/tracker-db-manager.h
@@ -21,6 +21,7 @@
#define __LIBTRACKER_DB_MANAGER_H__
#include <glib-object.h>
+#include <gio/gio.h>
#include "tracker-db-interface.h"
@@ -32,6 +33,24 @@ G_BEGIN_DECLS
#define TRACKER_TYPE_DB (tracker_db_get_type ())
+#define TRACKER_TYPE_DB_INTERFACE_POOL (tracker_db_interface_pool_get_type ())
+#define TRACKER_DB_INTERFACE_POOL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_DB_INTERFACE_POOL, TrackerDBInterfacePool))
+#define TRACKER_DB_INTERFACE_POOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_DB_INTERFACE_POOL, TrackerDBInterfacePoolClass))
+#define TRACKER_IS_DB_INTERFACE_POOL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_DB_INTERFACE_POOL))
+#define TRACKER_IS_DB_INTERFACE_POOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((o), TRACKER_TYPE_DB_INTERFACE_POOL))
+#define TRACKER_DB_INTERFACE_POOL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_DB_INTERFACE_POOL, TrackerDBInterfacePoolClass))
+
+typedef struct TrackerDBInterfacePool TrackerDBInterfacePool;
+typedef struct TrackerDBInterfacePoolClass TrackerDBInterfacePoolClass;
+
+struct TrackerDBInterfacePool {
+ GObject parent_instance;
+};
+
+struct TrackerDBInterfacePoolClass {
+ GObjectClass parent_class;
+};
+
typedef enum {
TRACKER_DB_UNKNOWN,
TRACKER_DB_METADATA,
@@ -65,6 +84,23 @@ gboolean tracker_db_manager_has_enough_space (void);
TrackerDBManagerFlags
tracker_db_manager_get_flags (void);
+/* TrackerDBInterfacePool methods */
+GType tracker_db_interface_pool_get_type (void) G_GNUC_CONST;
+
+TrackerDBInterfacePool * tracker_db_interface_pool_new (void);
+
+TrackerDBResultSet * tracker_db_interface_pool_execute_query_finish (TrackerDBInterfacePool *pool,
+ GAsyncResult *res,
+ GError **error);
+
+void tracker_db_interface_pool_execute_query_async (TrackerDBInterfacePool *pool,
+ guint priority,
+ const gchar *query,
+ GValueArray *bind_values,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __LIBTRACKER_DB_MANAGER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]