tracker r1381 - in branches/indexer-split: . src/libtracker-db src/trackerd
- From: pvanhoof svn gnome org
- To: svn-commits-list gnome org
- Subject: tracker r1381 - in branches/indexer-split: . src/libtracker-db src/trackerd
- Date: Thu, 8 May 2008 18:51:14 +0100 (BST)
Author: pvanhoof
Date: Thu May 8 17:51:14 2008
New Revision: 1381
URL: http://svn.gnome.org/viewvc/tracker?rev=1381&view=rev
Log:
2008-05-08 Philip Van Hoof <pvanhoof gnome org>
* src/trackerd/tracker-db-sqlite.c:
* src/libtracker-db/tracker-db-interface-sqlite.h:
* src/libtracker-db/tracker-db-interface-sqlite.c: Corrected the
GThreadQueue to have ALL sqlite_* calls in the same thread. This
work needs some refactoring later. Especially the changes in
tracker-db-sqlite.c are not quite the way I eventually want them.
Modified:
branches/indexer-split/ChangeLog
branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.c
branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.h
branches/indexer-split/src/trackerd/tracker-db-sqlite.c
Modified: branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.c
==============================================================================
--- branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.c (original)
+++ branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.c Thu May 8 17:51:14 2008
@@ -17,7 +17,6 @@
* Boston, MA 02110-1301, USA.
*/
-#include <sqlite3.h>
#include "tracker-db-interface-sqlite.h"
#define TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_DB_INTERFACE_SQLITE, TrackerDBInterfaceSqlitePrivate))
@@ -25,6 +24,26 @@
typedef struct TrackerDBInterfaceSqlitePrivate TrackerDBInterfaceSqlitePrivate;
typedef struct SqliteFunctionData SqliteFunctionData;
+typedef enum {
+ QUERY,
+ PROCEDURE,
+ PROCEDURE_LEN
+}TrackerDBQueryType;
+
+typedef struct {
+ GError **error;
+ TrackerDBResultSet *retval;
+ gboolean nowait;
+ va_list args;
+ gchar *query;
+ GObject *iface;
+ TrackerDBQueryType type;
+
+ GCond* condition;
+ gboolean had_callback;
+ GMutex *mutex;
+} TrackerDBQueryTask;
+
struct TrackerDBInterfaceSqlitePrivate {
gchar *filename;
sqlite3 *db;
@@ -44,25 +63,15 @@
TrackerDBFunc func;
};
-typedef struct {
- sqlite3_stmt *stmt;
- GError **error;
- TrackerDBResultSet *retval;
- gboolean nowait;
-
- GCond* condition;
- gboolean had_callback;
- GMutex *mutex;
-} TrackerDBQueryTask;
static void tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface);
-static void process_query (gpointer data, gpointer user_data);
static void free_db_query_task (TrackerDBQueryTask *task);
enum {
PROP_0,
PROP_FILENAME,
- PROP_IN_TRANSACTION
+ PROP_IN_TRANSACTION,
+ PROP_POOL
};
G_DEFINE_TYPE_WITH_CODE (TrackerDBInterfaceSqlite, tracker_db_interface_sqlite, G_TYPE_OBJECT,
@@ -110,6 +119,9 @@
case PROP_IN_TRANSACTION:
priv->in_transaction = g_value_get_boolean (value);
break;
+ case PROP_POOL:
+ priv->pool = g_value_get_pointer (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -132,6 +144,9 @@
case PROP_IN_TRANSACTION:
g_value_set_boolean (value, priv->in_transaction);
break;
+ case PROP_POOL:
+ g_value_set_pointer (value, priv->pool);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -144,9 +159,6 @@
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (object);
- /* This waits for all tasks being finished */
- g_thread_pool_free (priv->pool, TRUE, TRUE);
-
g_free (priv->filename);
g_hash_table_destroy (priv->statements);
@@ -182,6 +194,13 @@
PROP_IN_TRANSACTION,
"in-transaction");
+ g_object_class_install_property (object_class,
+ PROP_POOL,
+ g_param_spec_pointer ("pool",
+ "DB thread pool",
+ "Database connection pool",
+ G_PARAM_WRITABLE|G_PARAM_READABLE));
+
g_type_class_add_private (object_class,
sizeof (TrackerDBInterfaceSqlitePrivate));
}
@@ -193,6 +212,8 @@
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
+ priv->pool = NULL;
+
priv->procedures = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_free);
@@ -200,8 +221,6 @@
(GDestroyNotify) g_free,
(GDestroyNotify) sqlite3_finalize);
- priv->pool = g_thread_pool_new (process_query, db_interface,
- 1, TRUE, NULL);
}
static void
@@ -451,38 +470,131 @@
}
-static void
-process_query (gpointer data, gpointer user_data)
+void
+tracker_db_interface_sqlite_process_query (gpointer data, gpointer user_data)
{
+ TrackerDBInterfaceSqlitePrivate *priv;
TrackerDBQueryTask *task = (TrackerDBQueryTask *) data;
+ gboolean finalize_stmt = FALSE;
+ sqlite3_stmt *stmt = NULL;
+
+ priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (task->iface);
+
+ if (task->type == QUERY) {
+ /* If it's a plain query, no need for argument checking */
+
+ sqlite3_prepare_v2 (priv->db, task->query, -1, &stmt, NULL);
+
+ if (!stmt) {
+ g_set_error (task->error,
+ TRACKER_DB_INTERFACE_ERROR,
+ TRACKER_DB_QUERY_ERROR,
+ sqlite3_errmsg (priv->db));
+
+ goto ending;
+ }
+
+ /* If the stmt was created, we must free it up later, since
+ * unlike with procedures, we don't cache the stmt */
+
+ finalize_stmt = TRUE;
- task->retval = create_result_set_from_stmt (TRACKER_DB_INTERFACE_SQLITE (user_data),
- task->stmt, task->error);
+ } else if (task->type == PROCEDURE_LEN) {
+ /* If it's a procedure called with _len argument passing */
+
+ gint stmt_args, n_args, len;
+ gchar *str;
+
+ stmt = get_stored_stmt (TRACKER_DB_INTERFACE_SQLITE (task->iface), task->query);
+ stmt_args = sqlite3_bind_parameter_count (stmt);
+ n_args = 1;
+
+ while ((str = va_arg (task->args, gchar *)) != NULL) {
+ len = va_arg (task->args, gint);
+
+ if (len == -1) {
+ /* Assume we're dealing with strings */
+ sqlite3_bind_text (stmt, n_args, str, len, SQLITE_STATIC);
+ } else {
+ /* Deal with it as a blob */
+ sqlite3_bind_blob (stmt, n_args, str, len, SQLITE_STATIC);
+ }
+
+ n_args++;
+ }
+
+ /* Just panic if the number of arguments don't match */
+ g_assert (n_args != stmt_args);
+
+ } else {
+ /* If it's a normal procedure with normal argument passing */
+ gchar *str;
+ gint stmt_args, n_args;
+
+ stmt = get_stored_stmt (TRACKER_DB_INTERFACE_SQLITE (task->iface), task->query);
+ stmt_args = sqlite3_bind_parameter_count (stmt);
+ n_args = 1;
+
+ while ((str = va_arg (task->args, gchar *)) != NULL) {
+ sqlite3_bind_text (stmt, n_args, str, -1, SQLITE_STATIC);
+ n_args++;
+ }
+
+ /* Just panic if the number of arguments don't match */
+ g_assert (n_args != stmt_args);
+ }
+
+ /* If any of those three cases, execute the stmt */
+
+ task->retval = create_result_set_from_stmt (
+ TRACKER_DB_INTERFACE_SQLITE (task->iface),
+ stmt,
+ task->error);
+
+ending:
if (!task->nowait) {
+ /* If we are a blocking call, the caller will freeup and
+ * might consume the retval */
+
g_mutex_lock (task->mutex);
g_cond_broadcast (task->condition);
task->had_callback = TRUE;
g_mutex_unlock (task->mutex);
+
} else {
+ /* If not we freeup the retval, of course */
+
if (task->retval)
g_object_unref (task->retval);
free_db_query_task (task);
}
+
+ /* In case we were a succeeded query (procedures's stmt are cached) */
+
+ if (finalize_stmt)
+ sqlite3_finalize (stmt);
}
static TrackerDBQueryTask*
-create_db_query_task (sqlite3_stmt *stmt, GError **error, gboolean nowait)
+create_db_query_task (TrackerDBInterface *iface, const gchar *query, TrackerDBQueryType type, va_list args, GError **error)
{
TrackerDBQueryTask *task = g_slice_new (TrackerDBQueryTask);
+ /* GCond infrastructure */
task->mutex = g_mutex_new ();
task->condition = g_cond_new ();
task->had_callback = FALSE;
- task->nowait = nowait;
- task->stmt = stmt;
+ /* Must set */
task->error = error;
+ task->iface = g_object_ref (iface);
+ task->type = type;
+ task->query = g_strdup (query);
+ task->args = args;
+
+ /* Defaults */
+ task->nowait = FALSE;
return task;
}
@@ -490,6 +602,8 @@
static void
wait_for_db_query_task (TrackerDBQueryTask *task)
{
+ /* This simply waits for the GCond to become broadcasted */
+
g_mutex_lock (task->mutex);
if (!task->had_callback)
g_cond_wait (task->condition, task->mutex);
@@ -499,9 +613,12 @@
static void
free_db_query_task (TrackerDBQueryTask *task)
{
+ /* Freeing up resources of a db-query-task */
+
+ g_free (task->query);
+ g_object_unref (task->iface);
g_mutex_free (task->mutex);
g_cond_free (task->condition);
-
g_slice_free (TrackerDBQueryTask, task);
}
@@ -512,26 +629,12 @@
va_list args)
{
TrackerDBInterfaceSqlitePrivate *priv;
- sqlite3_stmt *stmt;
- gint stmt_args, n_args;
- gchar *str;
TrackerDBResultSet *retval;
TrackerDBQueryTask *task;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
- stmt = get_stored_stmt (TRACKER_DB_INTERFACE_SQLITE (db_interface), procedure_name);
- stmt_args = sqlite3_bind_parameter_count (stmt);
- n_args = 1;
-
- while ((str = va_arg (args, gchar *)) != NULL) {
- sqlite3_bind_text (stmt, n_args, str, -1, SQLITE_STATIC);
- n_args++;
- }
-
- /* Just panic if the number of arguments don't match */
- g_assert (n_args != stmt_args);
- task = create_db_query_task (stmt, error, FALSE);
+ task = create_db_query_task (db_interface, procedure_name, PROCEDURE, args, error);
g_thread_pool_push (priv->pool, task, NULL);
wait_for_db_query_task (task);
retval = task->retval;
@@ -549,25 +652,13 @@
va_list args)
{
TrackerDBInterfaceSqlitePrivate *priv;
- sqlite3_stmt *stmt;
- gint stmt_args, n_args;
- gchar *str;
TrackerDBQueryTask *task;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
- stmt = get_stored_stmt (TRACKER_DB_INTERFACE_SQLITE (db_interface), procedure_name);
- stmt_args = sqlite3_bind_parameter_count (stmt);
- n_args = 1;
- while ((str = va_arg (args, gchar *)) != NULL) {
- sqlite3_bind_text (stmt, n_args, str, -1, SQLITE_STATIC);
- n_args++;
- }
-
- /* Just panic if the number of arguments don't match */
- g_assert (n_args != stmt_args);
+ task = create_db_query_task (db_interface, procedure_name, PROCEDURE, args, error);
+ task->nowait = TRUE;
- task = create_db_query_task (stmt, error, TRUE);
g_thread_pool_push (priv->pool, task, NULL);
return;
@@ -581,38 +672,18 @@
va_list args)
{
TrackerDBInterfaceSqlitePrivate *priv;
- sqlite3_stmt *stmt;
- gint stmt_args, n_args, len;
- gchar *str;
TrackerDBResultSet *retval;
TrackerDBQueryTask *task;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
- stmt = get_stored_stmt (TRACKER_DB_INTERFACE_SQLITE (db_interface), procedure_name);
- stmt_args = sqlite3_bind_parameter_count (stmt);
- n_args = 1;
-
- while ((str = va_arg (args, gchar *)) != NULL) {
- len = va_arg (args, gint);
-
- if (len == -1) {
- /* Assume we're dealing with strings */
- sqlite3_bind_text (stmt, n_args, str, len, SQLITE_STATIC);
- } else {
- /* Deal with it as a blob */
- sqlite3_bind_blob (stmt, n_args, str, len, SQLITE_STATIC);
- }
- n_args++;
- }
-
- /* Just panic if the number of arguments don't match */
- g_assert (n_args != stmt_args);
+ task = create_db_query_task (db_interface, procedure_name, PROCEDURE_LEN, args, error);
- task = create_db_query_task (stmt, error, FALSE);
g_thread_pool_push (priv->pool, task, NULL);
+
wait_for_db_query_task (task);
retval = task->retval;
+
free_db_query_task (task);
return retval;
@@ -626,29 +697,17 @@
TrackerDBInterfaceSqlitePrivate *priv;
TrackerDBResultSet *retval;
TrackerDBQueryTask *task;
- sqlite3_stmt *stmt;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
- sqlite3_prepare_v2 (priv->db, query, -1, &stmt, NULL);
+ task = create_db_query_task (db_interface, query, QUERY, NULL, error);
- if (!stmt) {
- g_set_error (error,
- TRACKER_DB_INTERFACE_ERROR,
- TRACKER_DB_QUERY_ERROR,
- sqlite3_errmsg (priv->db));
- return NULL;
- }
-
- task = create_db_query_task (stmt, error, FALSE);
g_thread_pool_push (priv->pool, task, NULL);
+
wait_for_db_query_task (task);
retval = task->retval;
- free_db_query_task (task);
- /* This is different? (it's like in the original code before
- * the threadpool) */
- sqlite3_finalize (stmt);
+ free_db_query_task (task);
return retval;
@@ -665,10 +724,10 @@
}
TrackerDBInterface *
-tracker_db_interface_sqlite_new (const gchar *filename)
+tracker_db_interface_sqlite_new (const gchar *filename, GThreadPool *pool)
{
return g_object_new (TRACKER_TYPE_DB_INTERFACE_SQLITE,
- "filename", filename,
+ "filename", filename, "pool", pool,
NULL);
}
Modified: branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.h
==============================================================================
--- branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.h (original)
+++ branches/indexer-split/src/libtracker-db/tracker-db-interface-sqlite.h Thu May 8 17:51:14 2008
@@ -20,6 +20,8 @@
#ifndef __TRACKER_DB_INTERFACE_SQLITE_H__
#define __TRACKER_DB_INTERFACE_SQLITE_H__
+#include <sqlite3.h>
+
#include "tracker-db-interface.h"
G_BEGIN_DECLS
@@ -31,6 +33,7 @@
#define TRACKER_IS_DB_INTERFACE_SQLITE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((o), TRACKER_TYPE_DB_INTERFACE_SQLITE))
#define TRACKER_DB_INTERFACE_SQLITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_DB_INTERFACE_SQLITE, TrackerDBInterfaceSqliteClass))
+
typedef struct TrackerDBInterfaceSqlite TrackerDBInterfaceSqlite;
typedef struct TrackerDBInterfaceSqliteClass TrackerDBInterfaceSqliteClass;
@@ -52,7 +55,7 @@
GType tracker_db_interface_sqlite_get_type (void);
-TrackerDBInterface * tracker_db_interface_sqlite_new (const gchar *filename);
+TrackerDBInterface * tracker_db_interface_sqlite_new (const gchar *filename, GThreadPool *pool);
void tracker_db_interface_sqlite_create_function (TrackerDBInterface *interface,
const gchar *name,
@@ -64,6 +67,7 @@
gint64 tracker_db_interface_sqlite_get_last_insert_id (TrackerDBInterfaceSqlite *interface);
+void tracker_db_interface_sqlite_process_query (gpointer data, gpointer user_data);
G_END_DECLS
Modified: branches/indexer-split/src/trackerd/tracker-db-sqlite.c
==============================================================================
--- branches/indexer-split/src/trackerd/tracker-db-sqlite.c (original)
+++ branches/indexer-split/src/trackerd/tracker-db-sqlite.c Thu May 8 17:51:14 2008
@@ -585,6 +585,20 @@
tracker_debug ("Database closed");
}
+
+/* TODO: refactor this to a better location. This is the threadpool shared by
+ * all SQLite connections. I noticed that having a thread per connection is
+ * not sufficient. All statements must happen sequential ... */
+
+static GThreadPool *pool = NULL;
+
+/* TODO: the rafactor to a better location should perform this at-exit. For
+ * example when the desktop-session alarms that the system is shutting down,
+ * and when the trackerd process is exiting.
+ *
+ * g_thread_pool_free (priv->pool, TRUE, TRUE);
+ **/
+
static TrackerDBInterface *
open_db (const char *dir, const char *name, gboolean *create_table)
{
@@ -592,6 +606,10 @@
gboolean db_exists;
char *dbname;
+ if (!pool)
+ pool = g_thread_pool_new (tracker_db_interface_sqlite_process_query,
+ NULL, 1, TRUE, NULL);
+
dbname = g_build_filename (dir, name, NULL);
db_exists = g_file_test (dbname, G_FILE_TEST_IS_REGULAR);
@@ -603,7 +621,10 @@
*create_table = db_exists;
}
- db = tracker_db_interface_sqlite_new (dbname);
+ /* We pass a GThreadPool here, it should be the same pool for all opened
+ * SQLite databases */
+
+ db = tracker_db_interface_sqlite_new (dbname, pool);
tracker_db_interface_set_procedure_table (db, prepared_queries);
g_free (dbname);
@@ -857,7 +878,6 @@
{
DBConnection *db_con;
gboolean create_table = FALSE;
-
db_con = g_new0 (DBConnection, 1);
db_con->db = open_db (tracker->data_dir, TRACKER_INDEXER_FILE_META_DB_FILENAME, &create_table);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]