[tracker/binary-log-2: 56/56] Reimplemented backup and restore support



commit 5969e12a866cac6bfcc9b4f548470f94bb1f15f2
Author: Philip Van Hoof <philip codeminded be>
Date:   Thu Jan 7 12:36:13 2010 +0100

    Reimplemented backup and restore support

 src/libtracker-data/tracker-data-backup.c       |   52 +++++--
 src/libtracker-data/tracker-data-backup.h       |    3 +
 src/libtracker-db/tracker-db-interface-sqlite.c |   24 ---
 src/libtracker-db/tracker-db-interface.c        |   15 --
 src/libtracker-db/tracker-db-interface.h        |    4 -
 src/libtracker-db/tracker-db-manager.c          |  215 ++++++++++++++++-------
 src/libtracker-db/tracker-db-manager.h          |   27 ++--
 7 files changed, 214 insertions(+), 126 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-backup.c b/src/libtracker-data/tracker-data-backup.c
index cdff110..869fb54 100644
--- a/src/libtracker-data/tracker-data-backup.c
+++ b/src/libtracker-data/tracker-data-backup.c
@@ -24,6 +24,7 @@
 
 #include <libtracker-db/tracker-db-manager.h>
 #include <libtracker-db/tracker-db-journal.h>
+#include <libtracker-data/tracker-data-manager.h>
 
 #include "tracker-data-backup.h"
 
@@ -35,6 +36,12 @@ typedef struct {
 	GError *error;
 } BackupSaveInfo;
 
+GQuark
+tracker_data_backup_error_quark (void)
+{
+	return g_quark_from_static_string (TRACKER_DATA_BACKUP_ERROR_DOMAIN);
+}
+
 static void
 free_backup_save_info (BackupSaveInfo *info)
 {
@@ -89,6 +96,10 @@ tracker_data_backup_save (GFile *destination,
 	info->user_data = user_data;
 	info->destroy = destroy;
 
+	/* It's fine to copy this asynchronous: the journal replay code can or 
+	 * should cope with unfinished entries at the end of the file, while
+	 * restoring a backup made this way. */
+
 	g_file_copy_async (info->journal, info->destination,
 	                   G_FILE_COPY_OVERWRITE,
 	                   G_PRIORITY_HIGH,
@@ -119,9 +130,6 @@ tracker_data_backup_restore (GFile *journal,
 {
 	BackupSaveInfo *info;
 
-	tracker_db_manager_disconnect ();
-	tracker_db_journal_shutdown ();
-
 	info = g_new0 (BackupSaveInfo, 1);
 	info->destination = g_file_new_for_path (tracker_db_journal_get_filename ());
 	info->journal = g_object_ref (journal);
@@ -129,18 +137,38 @@ tracker_data_backup_restore (GFile *journal,
 	info->user_data = user_data;
 	info->destroy = destroy;
 
-	/* TODO, this depends on Jürg's replay APIs */
+	if (g_file_query_exists (info->journal, NULL)) {
+		TrackerDBManagerFlags flags = tracker_db_manager_get_flags ();
+		gboolean is_first;
+
+		tracker_db_manager_move_to_temp ();
+		tracker_data_manager_shutdown ();
 
-	g_file_copy (info->journal, info->destination,
-	             G_FILE_COPY_OVERWRITE,
-	             NULL, NULL, NULL,
-	             &info->error);
+		/* Synchronous: we don't want the mainloop to run while copying the
+		 * journal, as nobody should be writing anything at this point */
 
-	tracker_db_journal_init (NULL);
-	/* tracker_db_journal_replay (); */
-	tracker_db_manager_reconnect ();
+		g_file_copy (info->journal, info->destination,
+		             G_FILE_COPY_OVERWRITE,
+		             NULL, NULL, NULL,
+		             &info->error);
 
-	tracker_db_backup_sync_fts ();
+		tracker_db_manager_init_locations ();
+		tracker_db_journal_init (NULL);
+
+		if (info->error) {
+			tracker_db_manager_restore_from_temp ();
+		} else {
+			tracker_db_manager_remove_temp ();
+		}
+
+		tracker_db_journal_shutdown ();
+
+		tracker_data_manager_init (flags, NULL, &is_first);
+
+	} else {
+		g_set_error (&info->error, TRACKER_DATA_BACKUP_ERROR, 0, 
+		             "Backup file doesn't exist");
+	}
 
 	g_idle_add (on_restore_done, info);
 }
diff --git a/src/libtracker-data/tracker-data-backup.h b/src/libtracker-data/tracker-data-backup.h
index c5abf06..8dc4acf 100644
--- a/src/libtracker-data/tracker-data-backup.h
+++ b/src/libtracker-data/tracker-data-backup.h
@@ -30,6 +30,9 @@ G_BEGIN_DECLS
 #error "only <libtracker-data/tracker-data.h> must be included directly."
 #endif
 
+#define TRACKER_DATA_BACKUP_ERROR_DOMAIN "TrackerBackup"
+#define TRACKER_DATA_BACKUP_ERROR        tracker_data_backup_error_quark()
+
 typedef void (*TrackerDataBackupFinished) (GError *error, gpointer user_data);
 
 GQuark tracker_data_backup_error_quark (void);
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.c b/src/libtracker-db/tracker-db-interface-sqlite.c
index 144c20d..5420e32 100644
--- a/src/libtracker-db/tracker-db-interface-sqlite.c
+++ b/src/libtracker-db/tracker-db-interface-sqlite.c
@@ -125,8 +125,6 @@ static GType tracker_db_statement_sqlite_get_type (void);
 static void tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface);
 static void tracker_db_statement_sqlite_iface_init (TrackerDBStatementIface *iface);
 static void tracker_db_cursor_sqlite_iface_init (TrackerDBCursorIface *iface);
-static void tracker_db_interface_sqlite_disconnect (TrackerDBInterface *db_interface);
-static void tracker_db_interface_sqlite_reconnect  (TrackerDBInterface *db_interface);
 
 static TrackerDBStatementSqlite * tracker_db_statement_sqlite_new (TrackerDBInterfaceSqlite     *db_interface,
                                                                    sqlite3_stmt                         *sqlite_stmt);
@@ -754,8 +752,6 @@ tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface)
 {
 	iface->create_statement = tracker_db_interface_sqlite_create_statement;
 	iface->execute_query = tracker_db_interface_sqlite_execute_query;
-	iface->disconnect  = tracker_db_interface_sqlite_disconnect;
-	iface->reconnect  = tracker_db_interface_sqlite_reconnect;
 }
 
 TrackerDBInterface *
@@ -1156,26 +1152,6 @@ tracker_db_cursor_sqlite_get_string (TrackerDBCursor *cursor,  guint column)
 	return (const gchar *) sqlite3_column_text (priv->stmt, column);
 }
 
-static void
-tracker_db_interface_sqlite_disconnect (TrackerDBInterface *db_interface)
-{
-	TrackerDBInterfaceSqlitePrivate *priv;
-
-	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
-
-	close_database (priv);
-}
-
-static void
-tracker_db_interface_sqlite_reconnect (TrackerDBInterface *db_interface)
-{
-	TrackerDBInterfaceSqlitePrivate *priv;
-
-	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
-
-	open_database (priv);
-	prepare_database (priv);
-}
 
 static TrackerDBResultSet *
 tracker_db_statement_sqlite_execute (TrackerDBStatement                  *stmt,
diff --git a/src/libtracker-db/tracker-db-interface.c b/src/libtracker-db/tracker-db-interface.c
index db296b2..881c9e7 100644
--- a/src/libtracker-db/tracker-db-interface.c
+++ b/src/libtracker-db/tracker-db-interface.c
@@ -390,21 +390,6 @@ tracker_db_interface_end_transaction (TrackerDBInterface *interface)
 	return TRUE;
 }
 
-void
-tracker_db_interface_disconnect (TrackerDBInterface  *interface)
-{
-	g_return_if_fail (TRACKER_IS_DB_INTERFACE (interface));
-
-	TRACKER_DB_INTERFACE_GET_IFACE (interface)->disconnect (interface);
-}
-
-void
-tracker_db_interface_reconnect (TrackerDBInterface  *interface)
-{
-	g_return_if_fail (TRACKER_IS_DB_INTERFACE (interface));
-
-	TRACKER_DB_INTERFACE_GET_IFACE (interface)->reconnect (interface);
-}
 
 void
 tracker_db_statement_bind_double (TrackerDBStatement    *stmt,
diff --git a/src/libtracker-db/tracker-db-interface.h b/src/libtracker-db/tracker-db-interface.h
index 7c466a8..7b38b73 100644
--- a/src/libtracker-db/tracker-db-interface.h
+++ b/src/libtracker-db/tracker-db-interface.h
@@ -76,8 +76,6 @@ struct TrackerDBInterfaceIface {
 	TrackerDBResultSet * (* execute_query)    (TrackerDBInterface  *interface,
 	                                           GError             **error,
 	                                           const gchar         *query);
-	void                 (* disconnect)       (TrackerDBInterface  *interface);
-	void                 (* reconnect)        (TrackerDBInterface  *interface);
 };
 
 struct TrackerDBStatementIface {
@@ -157,8 +155,6 @@ TrackerDBResultSet *tracker_db_interface_execute_query     (TrackerDBInterface
 
 gboolean            tracker_db_interface_start_transaction (TrackerDBInterface  *interface);
 gboolean            tracker_db_interface_end_transaction   (TrackerDBInterface  *interface);
-void                tracker_db_interface_disconnect        (TrackerDBInterface  *interface);
-void                tracker_db_interface_reconnect         (TrackerDBInterface  *interface);
 void                tracker_db_statement_bind_double       (TrackerDBStatement  *stmt,
                                                             int                  index,
                                                             double               value);
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index 913db90..8ace824 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -146,20 +146,22 @@ static TrackerDBDefinition dbs[] = {
 	  0 },
 };
 
-static gboolean                    db_exec_no_reply    (TrackerDBInterface *iface,
-                                                        const gchar        *query,
-                                                        ...);
+static gboolean            db_exec_no_reply    (TrackerDBInterface *iface,
+                                                const gchar        *query,
+                                                ...);
 static TrackerDBInterface *db_interface_create (TrackerDB           db);
 static TrackerDBInterface *tracker_db_manager_get_db_interfaces     (gint num, ...);
 static TrackerDBInterface *tracker_db_manager_get_db_interfaces_ro  (gint num, ...);
 
-static gboolean                    initialized;
-static gchar              *sql_dir;
-static gchar              *data_dir;
-static gchar              *user_data_dir;
-static gchar              *sys_tmp_dir;
-static gpointer                    db_type_enum_class_pointer;
-static TrackerDBInterface *resources_iface;
+static gboolean              initialized;
+static gboolean              locations_initialized;
+static gchar                *sql_dir;
+static gchar                *data_dir = NULL;
+static gchar                *user_data_dir = NULL;
+static gchar                *sys_tmp_dir = NULL;
+static gpointer              db_type_enum_class_pointer;
+static TrackerDBInterface   *resources_iface;
+static TrackerDBManagerFlags old_flags = 0;
 
 static const gchar *
 location_to_directory (TrackerDBLocation location)
@@ -297,6 +299,12 @@ function_regexp (TrackerDBInterface *interface,
 	return result;
 }
 
+TrackerDBManagerFlags
+tracker_db_manager_get_flags (void)
+{
+	return old_flags;
+}
+
 static void
 function_group_concat_step (TrackerDBInterface *interface,
                             void               *aggregate_context,
@@ -847,7 +855,7 @@ db_interface_create (TrackerDB db)
 }
 
 static void
-db_manager_remove_all (gboolean rm_backup_and_log)
+db_manager_remove_all (gboolean rm_journal)
 {
 	guint i;
 
@@ -863,7 +871,7 @@ db_manager_remove_all (gboolean rm_backup_and_log)
 		g_unlink (dbs[i].abs_filename);
 	}
 
-	if (rm_backup_and_log) {
+	if (rm_journal) {
 		GFile *file;
 		gchar *cpath;
 
@@ -1053,6 +1061,38 @@ db_recreate_all (void)
 	}
 }
 
+void
+tracker_db_manager_init_locations (void)
+{
+	const gchar *dir;
+	guint i;
+	gchar *filename;
+
+	filename = g_strdup_printf ("tracker-%s", g_get_user_name ());
+	sys_tmp_dir = g_build_filename (g_get_tmp_dir (), filename, NULL);
+	g_free (filename);
+
+	user_data_dir = g_build_filename (g_get_user_data_dir (),
+	                                  "tracker",
+	                                  "data",
+	                                  NULL);
+
+	data_dir = g_build_filename (g_get_user_cache_dir (),
+	                             "tracker",
+	                             NULL);
+
+	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+		dir = location_to_directory (dbs[i].location);
+		dbs[i].abs_filename = g_build_filename (dir, dbs[i].file, NULL);
+
+		if (old_flags & TRACKER_DB_MANAGER_LOW_MEMORY_MODE) {
+			dbs[i].cache_size /= 2;
+		}
+	}
+
+	locations_initialized = TRUE;
+}
+
 gboolean
 tracker_db_manager_init (TrackerDBManagerFlags  flags,
                          gboolean              *first_time,
@@ -1094,7 +1134,11 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 	/* Set up locations */
 	g_message ("Setting database locations");
 
+	old_flags = flags;
+
 	filename = g_strdup_printf ("tracker-%s", g_get_user_name ());
+	if (sys_tmp_dir)
+		g_free (sys_tmp_dir);
 	sys_tmp_dir = g_build_filename (g_get_tmp_dir (), filename, NULL);
 	g_free (filename);
 
@@ -1108,11 +1152,17 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 		sql_dir = g_strdup (env_path);
 	}
 
+	if (user_data_dir)
+		g_free (user_data_dir);
+
 	user_data_dir = g_build_filename (g_get_user_data_dir (),
 	                                  "tracker",
 	                                  "data",
 	                                  NULL);
 
+	if (data_dir)
+		g_free (data_dir);
+
 	data_dir = g_build_filename (g_get_user_cache_dir (),
 	                             "tracker",
 	                             NULL);
@@ -1142,6 +1192,8 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
 		/* Fill absolute path for the database */
 		dir = location_to_directory (dbs[i].location);
+		if (dbs[i].abs_filename)
+			g_free (dbs[i].abs_filename);
 		dbs[i].abs_filename = g_build_filename (dir, dbs[i].file, NULL);
 
 		if (flags & TRACKER_DB_MANAGER_LOW_MEMORY_MODE) {
@@ -1166,6 +1218,8 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 		}
 	}
 
+	locations_initialized = TRUE;
+
 	/* If we are just initializing to remove the databases,
 	 * return here.
 	 */
@@ -1316,52 +1370,6 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 }
 
 void
-tracker_db_manager_disconnect (void)
-{
-	if (resources_iface) {
-		guint i;
-		TrackerDB attachments[2] = { TRACKER_DB_FULLTEXT,
-		                             TRACKER_DB_CONTENTS };
-
-		for (i = 0; i < 2; i++) {
-			TrackerDB db = attachments [i];
-
-			db_exec_no_reply (resources_iface,
-			                  "DETACH '%s'",
-			                  dbs[db].name);
-		}
-
-		tracker_db_interface_disconnect (resources_iface);
-	}
-}
-
-void
-tracker_db_manager_reconnect (void)
-{
-	if (resources_iface) {
-		guint i;
-		TrackerDB attachments[2] = { TRACKER_DB_FULLTEXT,
-		                             TRACKER_DB_CONTENTS };
-
-		tracker_db_interface_reconnect (resources_iface);
-
-		db_set_params (resources_iface,
-		               dbs[TRACKER_DB_METADATA].cache_size,
-		               dbs[TRACKER_DB_METADATA].page_size,
-		               TRUE);
-
-		for (i = 0; i < 2; i++) {
-			TrackerDB db = attachments [i];
-
-			db_exec_no_reply (resources_iface,
-			                  "ATTACH '%s' as '%s'",
-			                  dbs[db].abs_filename,
-			                  dbs[db].name);
-		}
-	}
-}
-
-void
 tracker_db_manager_shutdown (void)
 {
 	guint i;
@@ -1384,8 +1392,11 @@ tracker_db_manager_shutdown (void)
 	}
 
 	g_free (data_dir);
+	data_dir = NULL;
 	g_free (user_data_dir);
+	user_data_dir = NULL;
 	g_free (sys_tmp_dir);
+	sys_tmp_dir = NULL;
 	g_free (sql_dir);
 
 	if (resources_iface) {
@@ -1410,6 +1421,7 @@ tracker_db_manager_shutdown (void)
 	tracker_ontology_shutdown ();
 
 	initialized = FALSE;
+	locations_initialized = FALSE;
 
 	in_use_filename = g_build_filename (g_get_user_data_dir (),
 	                                    "tracker",
@@ -1423,11 +1435,94 @@ tracker_db_manager_shutdown (void)
 }
 
 void
-tracker_db_manager_remove_all (gboolean rm_backup_and_log)
+tracker_db_manager_remove_all (gboolean rm_journal)
 {
 	g_return_if_fail (initialized != FALSE);
 
-	db_manager_remove_all (rm_backup_and_log);
+	db_manager_remove_all (rm_journal);
+}
+
+
+void
+tracker_db_manager_move_to_temp (void)
+{
+	guint i;
+	gchar *cpath, *new_filename;
+
+	g_return_if_fail (initialized != FALSE);
+
+	g_message ("Moving all database files");
+
+	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+		new_filename = g_strdup_printf ("%s.tmp", dbs[i].abs_filename);
+		g_message ("  Renaming database:'%s' -> '%s'",
+		           dbs[i].abs_filename, new_filename);
+		g_rename (dbs[i].abs_filename, new_filename);
+		g_free (new_filename);
+	}
+
+	cpath = g_strdup (tracker_db_journal_get_filename ());
+	new_filename = g_strdup_printf ("%s.tmp", cpath);
+	g_message ("  Renaming journal:'%s' -> '%s'",
+	           cpath, new_filename);
+	g_rename (cpath, new_filename);
+	g_free (cpath);
+	g_free (new_filename);
+}
+
+
+void
+tracker_db_manager_restore_from_temp (void)
+{
+	guint i;
+	gchar *cpath, *new_filename;
+
+	g_return_if_fail (locations_initialized != FALSE);
+
+	g_message ("Moving all database files");
+
+	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+		new_filename = g_strdup_printf ("%s.tmp", dbs[i].abs_filename);
+		g_message ("  Renaming database:'%s' -> '%s'",
+		           dbs[i].abs_filename, new_filename);
+		g_rename (dbs[i].abs_filename, new_filename);
+		g_free (new_filename);
+	}
+
+	cpath = g_strdup (tracker_db_journal_get_filename ());
+	new_filename = g_strdup_printf ("%s.tmp", cpath);
+	g_message ("  Renaming journal:'%s' -> '%s'",
+	           cpath, new_filename);
+	g_rename (cpath, new_filename);
+	g_free (cpath);
+	g_free (new_filename);
+}
+
+void
+tracker_db_manager_remove_temp (void)
+{
+	guint i;
+	gchar *cpath, *new_filename;
+
+	g_return_if_fail (locations_initialized != FALSE);
+
+	g_message ("Removing all temp database files");
+
+	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+		new_filename = g_strdup_printf ("%s.tmp", dbs[i].abs_filename);
+		g_message ("  Removing temp database:'%s'",
+		           new_filename);
+		g_unlink (new_filename);
+		g_free (new_filename);
+	}
+
+	cpath = g_strdup (tracker_db_journal_get_filename ());
+	new_filename = g_strdup_printf ("%s.tmp", cpath);
+	g_message ("  Removing temp journal:'%s'",
+	           new_filename);
+	g_unlink (new_filename);
+	g_free (cpath);
+	g_free (new_filename);
 }
 
 void
diff --git a/src/libtracker-db/tracker-db-manager.h b/src/libtracker-db/tracker-db-manager.h
index f7c6636..5947652 100644
--- a/src/libtracker-db/tracker-db-manager.h
+++ b/src/libtracker-db/tracker-db-manager.h
@@ -47,17 +47,22 @@ typedef enum {
 	TRACKER_DB_MANAGER_READONLY         = 1 << 5
 } TrackerDBManagerFlags;
 
-GType               tracker_db_get_type                         (void) G_GNUC_CONST;
-gboolean            tracker_db_manager_init             (TrackerDBManagerFlags  flags,
-                                                         gboolean              *first_time,
-                                                         gboolean               shared_cache);
-void                tracker_db_manager_shutdown         (void);
-void                tracker_db_manager_remove_all       (gboolean               rm_backup_and_log);
-void                tracker_db_manager_optimize         (void);
-const gchar *       tracker_db_manager_get_file         (TrackerDB              db);
-TrackerDBInterface *tracker_db_manager_get_db_interface (void);
-void                tracker_db_manager_disconnect       (void);
-void                tracker_db_manager_reconnect        (void);
+GType               tracker_db_get_type                  (void) G_GNUC_CONST;
+gboolean            tracker_db_manager_init              (TrackerDBManagerFlags  flags,
+                                                          gboolean              *first_time,
+                                                          gboolean               shared_cache);
+void                tracker_db_manager_shutdown          (void);
+void                tracker_db_manager_remove_all        (gboolean               rm_journal);
+void                tracker_db_manager_optimize          (void);
+const gchar *       tracker_db_manager_get_file          (TrackerDB              db);
+TrackerDBInterface *tracker_db_manager_get_db_interface  (void);
+void                tracker_db_manager_remove_temp       (void);
+void                tracker_db_manager_move_to_temp      (void);
+void                tracker_db_manager_restore_from_temp (void);
+void                tracker_db_manager_init_locations    (void);
+
+TrackerDBManagerFlags
+                    tracker_db_manager_get_flags         (void);
 
 G_END_DECLS
 



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