[tracker/transient] libtracker-data: Reimplement transient properties to work with direct-access



commit 7f08d8788b3892dee4ff109e5b5294756686b342
Author: Philip Van Hoof <philip codeminded be>
Date:   Mon Nov 22 16:32:37 2010 +0100

    libtracker-data: Reimplement transient properties to work with direct-access

 src/libtracker-data/tracker-data-manager.c        |    4 +-
 src/libtracker-data/tracker-db-interface-sqlite.c |   35 ++++++++-
 src/libtracker-data/tracker-db-interface-sqlite.h |    6 +-
 src/libtracker-data/tracker-db-manager.c          |   83 +++++++++++++++++++--
 4 files changed, 115 insertions(+), 13 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 98b1ca3..78b28a1 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -2490,11 +2490,11 @@ create_decomposed_metadata_property_table (TrackerDBInterface *iface,
 			}
 
 			sql = g_string_new ("");
-			g_string_append_printf (sql, "CREATE %sTABLE \"%s_%s\" ("
+			g_string_append_printf (sql, "CREATE TABLE %s\"%s_%s\" ("
 			                             "ID INTEGER NOT NULL, "
 			                             "\"%s\" %s NOT NULL, "
 			                             "\"%s:graph\" INTEGER",
-			                             transient ? "TEMPORARY " : "",
+			                             transient ? "IF NOT EXISTS transient." : "",
 			                             service_name,
 			                             field_name,
 			                             field_name,
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c b/src/libtracker-data/tracker-db-interface-sqlite.c
index de7089f..9bf5464 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -51,6 +51,7 @@ struct TrackerDBInterface {
 	GObject parent_instance;
 
 	gchar *filename;
+	gchar *transient_filename;
 	sqlite3 *db;
 
 	GHashTable *dynamic_statements;
@@ -127,6 +128,7 @@ static gboolean            db_cursor_iter_next               (TrackerDBCursor
 enum {
 	PROP_0,
 	PROP_FILENAME,
+	PROP_TRANSIENT_FILENAME,
 	PROP_RO
 };
 
@@ -530,8 +532,10 @@ static void
 open_database (TrackerDBInterface *db_interface)
 {
 	int mode;
+	sqlite3 *transient = NULL;
 
 	g_assert (db_interface->filename != NULL);
+	g_assert (db_interface->transient_filename != NULL);
 
 	if (!db_interface->ro) {
 		mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
@@ -539,6 +543,12 @@ open_database (TrackerDBInterface *db_interface)
 		mode = SQLITE_OPEN_READONLY;
 	}
 
+	if (sqlite3_open_v2 (db_interface->transient_filename, &transient, mode | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) {
+		g_critical ("Could not open transient sqlite3 database:'%s'", db_interface->transient_filename);
+	} else {
+		sqlite3_close (transient);
+	}
+
 	if (sqlite3_open_v2 (db_interface->filename, &db_interface->db, mode | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) {
 		g_critical ("Could not open sqlite3 database:'%s'", db_interface->filename);
 	} else {
@@ -626,6 +636,9 @@ tracker_db_interface_sqlite_set_property (GObject       *object,
 	case PROP_RO:
 		db_iface->ro = g_value_get_boolean (value);
 		break;
+	case PROP_TRANSIENT_FILENAME:
+		db_iface->transient_filename = g_value_dup_string (value);
+		break;
 	case PROP_FILENAME:
 		db_iface->filename = g_value_dup_string (value);
 		break;
@@ -651,6 +664,9 @@ tracker_db_interface_sqlite_get_property (GObject    *object,
 	case PROP_FILENAME:
 		g_value_set_string (value, db_iface->filename);
 		break;
+	case PROP_TRANSIENT_FILENAME:
+		g_value_set_string (value, db_iface->transient_filename);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 	}
@@ -675,6 +691,7 @@ close_database (TrackerDBInterface *db_interface)
 #endif
 
 	rc = sqlite3_close (db_interface->db);
+
 	g_warn_if_fail (rc == SQLITE_OK);
 }
 
@@ -731,6 +748,7 @@ tracker_db_interface_sqlite_finalize (GObject *object)
 
 	g_message ("Closed sqlite3 database:'%s'", db_interface->filename);
 
+	g_free (db_interface->transient_filename);
 	g_free (db_interface->filename);
 	g_free (db_interface->busy_status);
 
@@ -758,6 +776,14 @@ tracker_db_interface_class_init (TrackerDBInterfaceClass *class)
 	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
 	g_object_class_install_property (object_class,
+	                                 PROP_TRANSIENT_FILENAME,
+	                                 g_param_spec_string ("transient-filename",
+	                                                      "DB transient-filename",
+	                                                      "DB transient-filename",
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
 	                                 PROP_RO,
 	                                 g_param_spec_boolean ("read-only",
 	                                                       "Read only",
@@ -1107,6 +1133,7 @@ create_result_set_from_stmt (TrackerDBInterface  *interface,
 			sqlite3_close (interface->db);
 
 			g_unlink (interface->filename);
+			g_unlink (interface->transient_filename);
 
 			g_error ("SQLite experienced an error with file:'%s'. "
 			         "It is either NOT a SQLite database or it is "
@@ -1191,18 +1218,22 @@ tracker_db_interface_execute_vquery (TrackerDBInterface  *db_interface,
 }
 
 TrackerDBInterface *
-tracker_db_interface_sqlite_new (const gchar *filename)
+tracker_db_interface_sqlite_new (const gchar *filename,
+                                 const gchar *transient_filename)
 {
 	return g_object_new (TRACKER_TYPE_DB_INTERFACE,
 	                     "filename", filename,
+	                     "transient-filename", transient_filename,
 	                     NULL);
 }
 
 TrackerDBInterface *
-tracker_db_interface_sqlite_new_ro (const gchar *filename)
+tracker_db_interface_sqlite_new_ro (const gchar *filename,
+                                    const gchar *transient_filename)
 {
 	return g_object_new (TRACKER_TYPE_DB_INTERFACE,
 	                     "filename", filename,
+	                     "transient-filename", filename,
 	                     "read-only", TRUE,
 	                     NULL);
 }
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.h b/src/libtracker-data/tracker-db-interface-sqlite.h
index 071a1b9..b5f5a22 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.h
+++ b/src/libtracker-data/tracker-db-interface-sqlite.h
@@ -32,8 +32,10 @@ G_BEGIN_DECLS
 
 #define TRACKER_COLLATION_NAME "TRACKER"
 
-TrackerDBInterface *tracker_db_interface_sqlite_new                    (const gchar              *filename);
-TrackerDBInterface *tracker_db_interface_sqlite_new_ro                 (const gchar              *filename);
+TrackerDBInterface *tracker_db_interface_sqlite_new                    (const gchar              *filename,
+                                                                        const gchar              *transient_filename);
+TrackerDBInterface *tracker_db_interface_sqlite_new_ro                 (const gchar              *filename,
+                                                                        const gchar              *transient_filename);
 gint64              tracker_db_interface_sqlite_get_last_insert_id     (TrackerDBInterface       *interface);
 void                tracker_db_interface_sqlite_enable_shared_cache    (void);
 void                tracker_db_interface_sqlite_fts_init               (TrackerDBInterface       *interface,
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index 92d8d48..ee0bde2 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -19,6 +19,9 @@
 
 #include "config.h"
 
+#include <sys/types.h>
+#include <pwd.h>
+
 #include <string.h>
 #include <stdlib.h>
 #include <regex.h>
@@ -155,6 +158,7 @@ static gpointer              db_type_enum_class_pointer;
 static TrackerDBManagerFlags old_flags = 0;
 static guint                 s_cache_size;
 static guint                 u_cache_size;
+static gchar                *transient_filename = NULL;
 
 static GStaticPrivate        interface_data_key = G_STATIC_PRIVATE_INIT;
 
@@ -215,11 +219,12 @@ db_set_params (TrackerDBInterface *iface,
 	pragmas_file = g_getenv ("TRACKER_PRAGMAS_FILE");
 
 	if (pragmas_file && g_file_get_contents (pragmas_file, &queries, NULL, NULL)) {
+		gchar *query;
 		g_debug ("PRAGMA's from file: %s", pragmas_file);
-		gchar *query = strtok (queries, "\n");
+		query = strtok (queries, "\n");
 		while (query) {
 			g_debug ("  INIT query: %s", query);
-			tracker_db_interface_execute_query (iface, NULL, query);
+			tracker_db_interface_execute_query (iface, NULL, "%s", query);
 			query = strtok (NULL, "\n");
 		}
 		g_free (queries);
@@ -289,12 +294,16 @@ db_interface_get (TrackerDB  type,
 	           path,
 	           db_type_to_string (type));
 
-	iface = tracker_db_interface_sqlite_new (path);
+	iface = tracker_db_interface_sqlite_new (path, transient_filename);
 
 	db_set_params (iface,
 	               dbs[type].cache_size,
 	               dbs[type].page_size);
 
+	db_exec_no_reply (iface,
+	                  "ATTACH '%s' as 'transient'",
+	                  transient_filename);
+
 	return iface;
 }
 
@@ -685,6 +694,50 @@ db_recreate_all (void)
 	db_set_locale (setlocale (LC_COLLATE, NULL));
 }
 
+static void
+tracker_db_manager_prepare_transient (gboolean readonly)
+{
+	gchar *shm_path;
+	struct passwd *pwd;
+
+	shm_path = g_build_filename (G_DIR_SEPARATOR_S "dev", "shm", NULL);
+
+	g_free (transient_filename);
+
+	if (g_file_test (shm_path, G_FILE_TEST_IS_DIR)) {
+		g_free (shm_path);
+		shm_path = g_build_filename (G_DIR_SEPARATOR_S "dev", "shm", g_get_user_name (), NULL);
+		transient_filename = g_build_filename (shm_path,
+		                                       "tracker-transient.db",
+		                                       NULL);
+	} else {
+		g_free (shm_path);
+		shm_path = g_build_path (g_get_tmp_dir (), g_get_user_name (), NULL);
+		transient_filename = g_build_filename (g_get_tmp_dir (),
+		                                       g_get_user_name (),
+		                                       "tracker-transient.db",
+		                                       NULL);
+	}
+
+	if (!readonly) {
+		if (!g_file_test (shm_path, G_FILE_TEST_IS_DIR)) {
+			g_mkdir_with_parents (shm_path, S_IRUSR | S_IWUSR | S_IXUSR |
+			                                S_IRGRP | S_IWGRP | S_IXGRP);
+		} else {
+			g_chmod (shm_path, S_IRUSR | S_IWUSR | S_IXUSR |
+			                   S_IRGRP | S_IWGRP | S_IXGRP);
+		}
+
+		pwd = getpwnam (g_get_user_name ());
+
+		if (pwd != NULL) {
+			chown (shm_path, pwd->pw_uid, -1);
+		}
+	}
+
+	g_free (shm_path);
+}
+
 void
 tracker_db_manager_init_locations (void)
 {
@@ -710,6 +763,8 @@ tracker_db_manager_init_locations (void)
 		dbs[i].abs_filename = g_build_filename (dir, dbs[i].file, NULL);
 	}
 
+	tracker_db_manager_prepare_transient (TRUE);
+
 	locations_initialized = TRUE;
 }
 
@@ -840,6 +895,8 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 		}
 	}
 
+	tracker_db_manager_prepare_transient (flags & TRACKER_DB_MANAGER_READONLY);
+
 	locations_initialized = TRUE;
 
 	/* If we are just initializing to remove the databases,
@@ -1058,6 +1115,8 @@ tracker_db_manager_shutdown (void)
 		}
 	}
 
+	g_free (transient_filename);
+	transient_filename = NULL;
 	g_free (data_dir);
 	data_dir = NULL;
 	g_free (user_data_dir);
@@ -1416,12 +1475,16 @@ tracker_db_manager_get_db_interfaces (gint num, ...)
 		TrackerDB db = va_arg (args, TrackerDB);
 
 		if (!connection) {
-			connection = tracker_db_interface_sqlite_new (dbs[db].abs_filename);
-
+			connection = tracker_db_interface_sqlite_new (dbs[db].abs_filename,
+			                                              transient_filename);
 			db_set_params (connection,
 			               dbs[db].cache_size,
 			               dbs[db].page_size);
 
+			db_exec_no_reply (connection,
+			                  "ATTACH '%s' as 'transient'",
+			                  transient_filename);
+
 		} else {
 			db_exec_no_reply (connection,
 			                  "ATTACH '%s' as '%s'",
@@ -1439,7 +1502,7 @@ static TrackerDBInterface *
 tracker_db_manager_get_db_interfaces_ro (gint num, ...)
 {
 	gint                n_args;
-	va_list                     args;
+	va_list             args;
 	TrackerDBInterface *connection = NULL;
 
 	g_return_val_if_fail (initialized != FALSE, NULL);
@@ -1449,10 +1512,16 @@ tracker_db_manager_get_db_interfaces_ro (gint num, ...)
 		TrackerDB db = va_arg (args, TrackerDB);
 
 		if (!connection) {
-			connection = tracker_db_interface_sqlite_new_ro (dbs[db].abs_filename);
+			connection = tracker_db_interface_sqlite_new_ro (dbs[db].abs_filename,
+			                                                 transient_filename);
 			db_set_params (connection,
 			               dbs[db].cache_size,
 			               dbs[db].page_size);
+
+			db_exec_no_reply (connection,
+			                  "ATTACH '%s' as 'transient'",
+			                  transient_filename);
+
 		} else {
 			db_exec_no_reply (connection,
 			                  "ATTACH '%s' as '%s'",



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