[tracker/dont-interrupt-create-statement] libtracker-db: Don't interrupt sqlite3_prepare_v2 with sqlite3_interrupt
- From: Philip Van Hoof <pvanhoof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/dont-interrupt-create-statement] libtracker-db: Don't interrupt sqlite3_prepare_v2 with sqlite3_interrupt
- Date: Mon, 24 May 2010 11:24:28 +0000 (UTC)
commit 415997ac4e13906b3930e558bfbc1515a55526be
Author: Philip Van Hoof <philip codeminded be>
Date: Mon May 24 13:17:34 2010 +0200
libtracker-db: Don't interrupt sqlite3_prepare_v2 with sqlite3_interrupt
We don't handle create_statement returning NULL due to sqlite3_prepare_v2 being
interrupted with our interrupt function that calls sqlite3_interrupt. Because
added interrupt handling for all callers of create_statement is a massive
undertaking in nearly all levels of the code (ensure_resource_id would need
error reporting, for example, among many many others) I decided to place a
simple mutex around sqlite3_interrupt and around the sqlite3_prepare_v2,
preventing sqlite3_interrupt from ever executing concurrently with
sqlite3_prepare_v2.
src/libtracker-db/tracker-db-interface-sqlite.c | 30 +++++++++++++++++++++-
1 files changed, 28 insertions(+), 2 deletions(-)
---
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.c b/src/libtracker-db/tracker-db-interface-sqlite.c
index c290d16..2c50fb3 100644
--- a/src/libtracker-db/tracker-db-interface-sqlite.c
+++ b/src/libtracker-db/tracker-db-interface-sqlite.c
@@ -61,7 +61,6 @@ typedef struct TrackerDBCursorSqliteClass TrackerDBCursorSqliteClass;
typedef struct TrackerDBStatementSqlite TrackerDBStatementSqlite;
typedef struct TrackerDBStatementSqliteClass TrackerDBStatementSqliteClass;
-
struct TrackerDBCursorSqlite {
GObject parent_instance;
TrackerDBCursorSqlitePrivate *priv;
@@ -82,6 +81,7 @@ struct TrackerDBInterfaceSqlitePrivate {
guint in_transaction : 1;
guint ro : 1;
guint fts_initialized : 1;
+ GMutex *interrupt_mutex;
};
struct TrackerDBStatementSqlitePrivate {
@@ -494,6 +494,8 @@ open_database (TrackerDBInterfaceSqlitePrivate *priv)
{
g_assert (priv->filename != NULL);
+ priv->interrupt_mutex = g_mutex_new ();
+
if (!priv->ro) {
if (sqlite3_open (priv->filename, &priv->db) != SQLITE_OK) {
g_critical ("Could not open sqlite3 database:'%s'", priv->filename);
@@ -652,6 +654,8 @@ tracker_db_interface_sqlite_finalize (GObject *object)
g_message ("Closed sqlite3 database:'%s'", priv->filename);
+ g_mutex_free (priv->interrupt_mutex);
+
g_free (priv->filename);
G_OBJECT_CLASS (tracker_db_interface_sqlite_parent_class)->finalize (object);
@@ -761,9 +765,21 @@ tracker_db_interface_sqlite_create_statement (TrackerDBInterface *db_interface,
{
TrackerDBInterfaceSqlitePrivate *priv;
TrackerDBStatementSqlite *stmt;
+ TrackerDBStatement *ret;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
+ /* This mutex prevents an interrupt from happening while we are preparing a
+ * query. We don't have any interrupt handling for create_statement at any
+ * place in the code, it would be a massive undertaking to support handling
+ * interrupting while preparing a query. Which is why we block the interrupt
+ * until after we prepared the query. Because prepared statements end up in
+ * a cache wont it happen often that this lock is needed. But still, we do
+ * need to protect against sqlite3_interrupt while sqlite3_prepare_v2 takes
+ * place, as the 'return NULL' isn't handled anywhere in the code. */
+
+ g_mutex_lock (priv->interrupt_mutex);
+
stmt = g_hash_table_lookup (priv->dynamic_statements, query);
if (!stmt) {
@@ -773,6 +789,9 @@ tracker_db_interface_sqlite_create_statement (TrackerDBInterface *db_interface,
if (sqlite3_prepare_v2 (priv->db, query, -1, &sqlite_stmt, NULL) != SQLITE_OK) {
g_critical ("Unable to prepare query '%s': %s", query, sqlite3_errmsg (priv->db));
+
+ g_mutex_unlock (priv->interrupt_mutex);
+
return NULL;
}
@@ -782,7 +801,11 @@ tracker_db_interface_sqlite_create_statement (TrackerDBInterface *db_interface,
tracker_db_statement_sqlite_reset (stmt);
}
- return g_object_ref (stmt);
+ ret = g_object_ref (stmt);
+
+ g_mutex_unlock (priv->interrupt_mutex);
+
+ return ret;
}
static TrackerDBResultSet *
@@ -909,7 +932,10 @@ tracker_db_interface_sqlite_interrupt (TrackerDBInterface *iface)
TrackerDBInterfaceSqlitePrivate *priv;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (iface);
+
+ g_mutex_lock (priv->interrupt_mutex);
sqlite3_interrupt (priv->db);
+ g_mutex_unlock (priv->interrupt_mutex);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]