[tracker] Squashed commit of the following:



commit 1f19ed577b308c2561277eeec151909c91883f89
Author: Philip Van Hoof <philip codeminded be>
Date:   Tue Aug 25 15:01:12 2009 +0200

    Squashed commit of the following:
    
    commit 65ef93d8e11f03b2d825f40b41a3bccb821abf07
    Merge: 08017cb 54e6080
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Tue Aug 25 14:58:34 2009 +0200
    
        Merge branch 'master' into urho-sync
    
        Conflicts:
        	tests/libtracker-data/tracker-ontology-test.c
        	tests/libtracker-data/tracker-sparql-test.c
    
    commit 08017cbb8a3e1a373f88c6842fb526e916009025
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Tue Aug 25 12:45:56 2009 +0200
    
        Limiting the size of the log file
    
    commit 2b6623eae4c52c232d05ae01ab77bdaca0f9d1ba
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 16:29:11 2009 +0200
    
        Added some code comments
    
    commit 28e0498331c6fe0914528cd17f035339931bfa53
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 16:14:44 2009 +0200
    
        Start save of backup over DBus after queue's commit
    
    commit 4c59007564f1138c01a66e2e45f891d157da03e8
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 15:57:19 2009 +0200
    
        Fixed restore on startup of meta.db is missing and meta-backup.db isn't
    
    commit e43ce2eaadda7759c3e5ca7aa73c8e40543343e2
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 15:17:37 2009 +0200
    
        Adding kill to soft-reset
    
    commit b7866eded285c138673c767e2979342c89fa1b37
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 14:50:38 2009 +0200
    
        Made DBus's Restore() synchronous
    
    commit 70eae9cb2c4747d226e687e10452e6e4054fcd27
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 14:23:31 2009 +0200
    
        Fixed path of the meta-backup.db file
    
    commit bbc39e88fa6affbe570676a304b7eee520e7e8e1
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 14:21:25 2009 +0200
    
        Fixed restore after tracker-processes -s
    
    commit a98ac7a5fcc9c4a6957ba292274a2211913ce06d
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 13:31:08 2009 +0200
    
        Revert changes to INSTALL file
    
    commit 0016d9d9a0811abb9a098b49da64db6c1febee86
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 12:39:22 2009 +0200
    
        Code cleanup
    
    commit a10c615c63e35c548d3255cdc93632012ab5ae69
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 12:24:02 2009 +0200
    
        Code cleanup
    
    commit 3de8d7d0a2447840bd4c4168a9993fc78d504ad3
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 12:02:58 2009 +0200
    
        Added transaction barriers to the journal player
    
    commit 6af3250b97b79c4adefa518306081c1e86e42be3
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 12:00:15 2009 +0200
    
        Improvement for tracker-processes util
    
    commit 636d9670bd79ca4f86350acd85818fcd5679527e
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 11:47:16 2009 +0200
    
        Fixed finding location of meta-backup.db
    
    commit d487838385db6ec4b3f7d89fc11440be60813a73
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 24 11:44:40 2009 +0200
    
        Play journal always when meta.db didn't exist
    
    commit 013b277d1f3079d228f20a8fc14b11da8d5f8f6e
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Aug 21 17:11:44 2009 +0200
    
        Changed the format of the log, playing it using mmap
    
    commit a61dbf091354411c093674105039e1546e7a3151
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Aug 21 11:19:23 2009 +0200
    
        No need to do an extra fsync of commit causes one already
    
    commit e329dbca27a1ee5258757a0ff0c051097ecb93a6
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Aug 21 11:12:39 2009 +0200
    
        Fixed logic, the timeout is for backup, the max for fsync
    
    commit ed462a8126c9a2314d4adb516183340067a96b7b
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Aug 21 11:06:14 2009 +0200
    
        Fixed another glitch
    
    commit 67fa0312d568718effb797d77308b5133d3d76e2
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Aug 21 11:00:46 2009 +0200
    
        Make it exact
    
    commit d5ab45435cc1a2e9b56fbafb04a82f150c843e51
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Aug 21 10:58:04 2009 +0200
    
        Make fsync happen less often on the journal
    
    commit 250362370069b56cd0b134fb7db02d9b561c52ef
    Author: Jürg Billeter <j bitron ch>
    Date:   Fri Aug 21 09:37:35 2009 +0200
    
        Remove raptor.h include
    
    commit 18048eeda22eb94030a32e6f59e4c5ca0fa53579
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Thu Aug 20 15:35:30 2009 +0200
    
        Several bugfixes in backup and restore
    
    commit 0bdb823b6b13081ff88a98c0e9bc0bb62d655e24
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Thu Aug 20 15:09:38 2009 +0200
    
        Playing the journal on restore
    
    commit b937a201f7588a4f401bc13f51e47a4754e1e3b2
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Thu Aug 20 14:58:54 2009 +0200
    
        Changed the paths of the meta-backup and the journal
    
    commit 142a32f01e4a43275d954e48b1134ba4a7a965db
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Thu Aug 20 12:47:04 2009 +0200
    
        Backup and restore support
    
    commit 2ef24a4563c2e6fab6f17b0a1926602135639cb4
    Merge: a7a7339 8a66865
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Thu Aug 20 10:56:00 2009 +0200
    
        Merge branch 'master' into urho-sync
    
    commit a7a73398baa8d87ecdb32b0228ffb78c5818a36e
    Merge: 2c25a57 d8aebcb
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Wed Aug 19 15:39:40 2009 +0200
    
        Merge branch 'master' into urho-sync
    
        Conflicts:
        	src/tracker-store/tracker-main.c
    
    commit 2c25a572dbadf53ed5d9316d1eb61c0655335e98
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Wed Aug 19 15:30:58 2009 +0200
    
        Atomic rename and journal load
    
    commit a3eec4151daadc9c575edc0174e2e610e50e61e4
    Merge: 82003a5 377dc98
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Wed Aug 19 15:16:18 2009 +0200
    
        Merge branch 'master' into urho-sync
    
    commit 82003a5114bb6fd3ee69190be56e251afb7adace
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Wed Aug 5 11:16:47 2009 +0200
    
        Don't perform the check when need_journal isn't passed
    
    commit 57e8168e31fcd5322798bd2b66f1f079b100ed76
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Wed Aug 5 10:43:02 2009 +0200
    
        Refactored the journal code a bit
    
    commit b37be6edbf55d3b43960fa87fd3b0322c9ae121a
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Tue Aug 4 16:42:39 2009 +0200
    
        Fixed a critical warning
    
    commit 06fee84f767a2363c8eac30ccd424ac1f932d975
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Tue Aug 4 16:35:55 2009 +0200
    
        Changed the logic about journal playing and meta-backup.db picking
    
    commit fab94fb68cc9b044ac84641ab4f80fba387233fd
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Tue Aug 4 14:11:21 2009 +0200
    
        Comment with a warning about the journal in a rare case
    
    commit 94ae1fbfa25b6c2faa1e073ec171c5f5bc6cb3d6
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Mon Aug 3 18:28:36 2009 +0200
    
        Restoring the db using a backup on corruption
    
    commit 47e8885909a6b89559788a1f789d2902eedadfb2
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Jul 31 17:45:19 2009 +0200
    
        Setting sync=off as the journal is being made now
    
    commit f697a726b69df2e91b5c5daeb31e9252fa2a3ba2
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Jul 31 17:43:28 2009 +0200
    
        Added missing files
    
    commit 9bcfa4e19b7042c7c315eecb9fb7d7939050bf36
    Author: Philip Van Hoof <philip codeminded be>
    Date:   Fri Jul 31 17:41:43 2009 +0200
    
        Experiment for journal synchronization mode

 data/dbus/tracker-backup.xml                    |    6 +-
 src/libtracker-data/tracker-data-backup.c       |  224 +++++++++++++++++---
 src/libtracker-data/tracker-data-backup.h       |   16 +-
 src/libtracker-data/tracker-data-manager.c      |    5 +-
 src/libtracker-data/tracker-data-manager.h      |    3 +-
 src/libtracker-db/Makefile.am                   |    8 +-
 src/libtracker-db/tracker-db-backup.c           |  269 +++++++++++++++++++++++
 src/libtracker-db/tracker-db-backup.h           |   51 +++++
 src/libtracker-db/tracker-db-interface-sqlite.c |  100 +++++++--
 src/libtracker-db/tracker-db-interface.c        |   18 ++
 src/libtracker-db/tracker-db-interface.h        |    4 +
 src/libtracker-db/tracker-db-journal.c          |  167 ++++++++++++++
 src/libtracker-db/tracker-db-journal.h          |   47 ++++
 src/libtracker-db/tracker-db-manager.c          |  169 +++++++++++++-
 src/libtracker-db/tracker-db-manager.h          |   13 +-
 src/tracker-store/tracker-backup.c              |   98 ++++++---
 src/tracker-store/tracker-backup.h              |    6 +-
 src/tracker-store/tracker-main.c                |   11 +-
 src/tracker-store/tracker-resources.c           |    4 +
 src/tracker-store/tracker-store.c               |  136 +++++++++++-
 src/tracker-store/tracker-store.h               |    5 +-
 src/tracker-utils/tracker-processes.c           |   15 +-
 tests/libtracker-data/tracker-ontology-test.c   |    2 +-
 tests/libtracker-data/tracker-sparql-test.c     |    2 +-
 24 files changed, 1242 insertions(+), 137 deletions(-)
---
diff --git a/data/dbus/tracker-backup.xml b/data/dbus/tracker-backup.xml
index 7ba81d2..44f93f0 100644
--- a/data/dbus/tracker-backup.xml
+++ b/data/dbus/tracker-backup.xml
@@ -4,11 +4,13 @@
   <interface name="org.freedesktop.Tracker1.Backup">
     <method name="Save">
       <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
-      <arg type="s" name="turtle-file-uri" direction="in" />
+      <arg type="s" name="destination-uri" direction="in" />
+      <arg type="s" name="journal-uri" direction="in" />
     </method>
     <method name="Restore">
       <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
-      <arg type="s" name="turtle-file-uri" direction="in" />
+      <arg type="s" name="backup-uri" direction="in" />
+      <arg type="s" name="journal-uri" direction="in" />
     </method>
   </interface>
 </node>
diff --git a/src/libtracker-data/tracker-data-backup.c b/src/libtracker-data/tracker-data-backup.c
index 9a548ae..fc2ddc3 100644
--- a/src/libtracker-data/tracker-data-backup.c
+++ b/src/libtracker-data/tracker-data-backup.c
@@ -23,63 +23,235 @@
 #include <glib.h>
 #include <glib/gstdio.h>
 
-#include <libtracker-data/tracker-data-query.h>
+#include <libtracker-db/tracker-db-manager.h>
+#include <libtracker-db/tracker-db-journal.h>
+#include <libtracker-db/tracker-db-backup.h>
 
 #include "tracker-data-backup.h"
 
 typedef struct {
-	TrackerBackupFinished callback;
+	GFile *destination, *journal, *file;
+	TrackerDataBackupFinished callback;
 	gpointer user_data;
 	GDestroyNotify destroy;
-} UnImplementedInfo;
+	GError *error;
+} BackupSaveInfo;
 
-GQuark
-tracker_data_backup_error_quark (void)
+static void
+free_backup_save_info (BackupSaveInfo *info)
 {
-	return g_quark_from_static_string ("tracker-data-backup-error-quark");
+	if (info->destination) {
+		g_object_unref (info->destination);
+	}
+	if (info->journal) {
+		g_object_unref (info->journal);
+	}
+	if (info->file) {
+		g_object_unref (info->file);
+	}
+
+	if (info->destroy) {
+		info->destroy (info->user_data);
+	}
+
+	g_clear_error (&info->error);
+
+	g_free (info);
 }
 
-static gboolean
-unimplemented (gpointer user_data)
+
+static void
+on_meta_copied (GObject *source_object,
+                GAsyncResult *res,
+                gpointer user_data)
 {
-	UnImplementedInfo *info = user_data;
+	BackupSaveInfo *info = user_data;
+	GError *error = NULL;
 
-	g_warning ("tracker_data_backup_save is unimplemented");
+	g_file_copy_finish (info->file, res, &error);
 
 	if (info->callback) {
-		GError *error = NULL;
+		info->callback (error, info->user_data);
+	}
 
-		g_set_error (&error,
-		             TRACKER_DB_BACKUP_ERROR,
-		             TRACKER_DB_BACKUP_ERROR_UNKNOWN,
-		             "tracker_data_backup_save is unimplemented");
+	free_backup_save_info (info);
 
-		info->callback (error, info->user_data);
-		g_clear_error (&error);
+	g_clear_error (&error);
+}
+
+static void
+on_journal_copied (GObject *source_object,
+                   GAsyncResult *res,
+                   gpointer user_data)
+{
+	BackupSaveInfo *info = user_data;
+	GError *error = NULL;
+
+	if (!g_file_copy_finish (info->journal, res, &error)) {
+		if (info->callback) {
+			info->callback (error, info->user_data);
+		}
+		free_backup_save_info (info);
+	} else {
+		g_file_copy_async (info->file, info->destination, 
+		                   G_FILE_COPY_OVERWRITE, 
+		                   G_PRIORITY_HIGH,
+		                   NULL, NULL, NULL,
+		                   on_meta_copied,
+		                   info);
 	}
 
-	if (info->destroy) {
-		info->destroy (info->user_data);
+	g_clear_error (&error);
+}
+
+static void
+save_copy_procedure (BackupSaveInfo *info)
+{
+	GFile *journal_o;
+
+	journal_o = g_file_new_for_path (tracker_db_journal_filename ());
+
+	if (g_file_query_exists (journal_o, NULL)) {
+		g_file_copy_async (journal_o, info->journal, 
+				   G_FILE_COPY_OVERWRITE, 
+				   G_PRIORITY_HIGH,
+				   NULL, NULL, NULL,
+				   on_journal_copied,
+				   info);
+	} else {
+		g_file_copy_async (info->file, info->destination, 
+		                   G_FILE_COPY_OVERWRITE, 
+		                   G_PRIORITY_HIGH,
+		                   NULL, NULL, NULL,
+		                   on_meta_copied,
+		                   info);
 	}
 
+	g_object_unref (journal_o);
+}
+
+static void
+on_backup_finished (GError *error, gpointer user_data)
+{
+	BackupSaveInfo *info = user_data;
+
+	if (error) {
+		if (info->callback) {
+			info->callback (error, info->user_data);
+		}
+		free_backup_save_info (info);
+		return;
+	}
+
+	save_copy_procedure (info);
 }
 
 void
-tracker_data_backup_save (GFile *turtle_file,
-                          TrackerBackupFinished callback,
+tracker_data_backup_save (GFile *destination,
+                          GFile *journal,
+                          TrackerDataBackupFinished callback,
                           gpointer user_data,
                           GDestroyNotify destroy)
 {
-	UnImplementedInfo *info = g_new(UnImplementedInfo, 1);
+	BackupSaveInfo *info;
 
+	info = g_new0 (BackupSaveInfo, 1);
+	info->destination = g_object_ref (destination);
+	info->journal = g_object_ref (journal);
 	info->callback = callback;
 	info->user_data = user_data;
 	info->destroy = destroy;
 
-	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
-	                 callback,
-	                 info,
-	                 NULL);
+	info->file = tracker_db_backup_file (NULL, TRACKER_DB_BACKUP_META_FILENAME);
+
+	if (g_file_query_exists (info->file, NULL)) {
+		/* Making a backup just means copying meta-backup.db */
+		save_copy_procedure (info);
+	} else {
+		/* If we don't have a meta-backup.db yet, we first make one */
+		tracker_db_backup_save (on_backup_finished, 
+		                        info, NULL);
+	}
 }
 
+static gboolean
+on_restore_done (gpointer user_data)
+{
+	BackupSaveInfo *info = user_data;
 
+	if (info->callback) {
+		info->callback (info->error, info->user_data);
+	}
+
+	free_backup_save_info (info);
+
+	return FALSE;
+}
+
+static void
+restore_copy_procedure (BackupSaveInfo *info)
+{
+	GFile *journal_d;
+	GError *error = NULL;
+
+	/* Restore should block the mainloop until finished */
+
+	journal_d = g_file_new_for_path (tracker_db_journal_filename ());
+
+	if (g_file_query_exists (journal_d, NULL)) {
+		g_file_copy (info->journal, journal_d, 
+		             G_FILE_COPY_OVERWRITE, 
+		             NULL, NULL, NULL,
+		             &error);
+	}
+
+	g_object_unref (journal_d);
+
+	if (error) {
+		goto error_handle;
+	}
+
+	g_file_copy (info->destination, info->file,
+	             G_FILE_COPY_OVERWRITE, 
+	             NULL, NULL, NULL,
+	             &error);
+
+	if (error) {
+		goto error_handle;
+	}
+
+error_handle:
+
+	info->error = error;
+}
+
+void
+tracker_data_backup_restore (GFile *backup,
+                             GFile *journal,
+                             TrackerDataBackupFinished callback,
+                             gpointer user_data,
+                             GDestroyNotify destroy)
+{
+	BackupSaveInfo *info;
+
+	tracker_db_manager_disconnect ();
+	tracker_db_journal_close ();
+
+	info = g_new0 (BackupSaveInfo, 1);
+	info->destination = g_object_ref (backup);
+	info->journal = g_object_ref (journal);
+	info->callback = callback;
+	info->user_data = user_data;
+	info->destroy = destroy;
+
+	info->file = tracker_db_backup_file (NULL, TRACKER_DB_BACKUP_META_FILENAME);
+
+	/* This is all synchronous, blocking the mainloop indeed */
+
+	restore_copy_procedure (info);
+
+	tracker_db_journal_open ();
+	tracker_db_manager_reconnect ();
+
+	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 e0dc7ad..11ab5ab 100644
--- a/src/libtracker-data/tracker-data-backup.h
+++ b/src/libtracker-data/tracker-data-backup.h
@@ -26,18 +26,16 @@
 
 G_BEGIN_DECLS
 
-#define TRACKER_DB_BACKUP_ERROR	    (tracker_data_backup_error_quark ())
-
-typedef enum {
-	TRACKER_DB_BACKUP_ERROR_UNKNOWN,
-} TrackerDBBackupError;
-
-typedef void (*TrackerBackupFinished)   (GError *error, gpointer user_data);
+typedef void (*TrackerDataBackupFinished)   (GError *error, gpointer user_data);
 
 GQuark    tracker_data_backup_error_quark (void);
 
-void      tracker_data_backup_save        (GFile     *turtle_file,
-                                           TrackerBackupFinished callback,
+void      tracker_data_backup_save        (GFile *destination, GFile *journal,
+                                           TrackerDataBackupFinished callback,
+                                           gpointer user_data,
+                                           GDestroyNotify destroy);
+void      tracker_data_backup_restore     (GFile *backup, GFile *journal,
+                                           TrackerDataBackupFinished callback,
                                            gpointer user_data,
                                            GDestroyNotify destroy);
 
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 4c63d59..a35fc2d 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -747,7 +747,8 @@ create_fts_table (TrackerDBInterface *iface)
 gboolean
 tracker_data_manager_init (TrackerDBManagerFlags       flags,
 			   const gchar                *test_schema,
-			   gboolean                   *first_time)
+			   gboolean                   *first_time,
+			   gboolean                   *need_journal)
 {
 	TrackerDBInterface *iface;
 	gboolean is_first_time_index;
@@ -756,7 +757,7 @@ tracker_data_manager_init (TrackerDBManagerFlags       flags,
 		return TRUE;
 	}
 
-	tracker_db_manager_init (flags, &is_first_time_index, FALSE);
+	tracker_db_manager_init (flags, &is_first_time_index, FALSE, need_journal);
 
 	if (first_time != NULL) {
 		*first_time = is_first_time_index;
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index e0cfe40..2a7c7e9 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -36,7 +36,8 @@ G_BEGIN_DECLS
 
 gboolean            tracker_data_manager_init              (TrackerDBManagerFlags       flags,
 							    const gchar                *test_schema,
-							    gboolean                   *first_time);
+							    gboolean                   *first_time,
+							    gboolean                   *need_journal);
 void                tracker_data_manager_shutdown          (void);
 
 gint64              tracker_data_manager_get_db_option_int64 (const gchar        *option);
diff --git a/src/libtracker-db/Makefile.am b/src/libtracker-db/Makefile.am
index 951359b..cbbfd00 100644
--- a/src/libtracker-db/Makefile.am
+++ b/src/libtracker-db/Makefile.am
@@ -18,13 +18,17 @@ libtracker_db_la_SOURCES = 						\
 	tracker-db-dbus.c						\
 	tracker-db-interface.c						\
 	tracker-db-interface-sqlite.c					\
-	tracker-db-manager.c
+	tracker-db-manager.c						\
+	tracker-db-backup.c						\
+	tracker-db-journal.c						
 
 noinst_HEADERS =							\
 	tracker-db-dbus.h						\
 	tracker-db-interface.h						\
 	tracker-db-interface-sqlite.h					\
-	tracker-db-manager.h 
+	tracker-db-manager.h 						\
+	tracker-db-backup.h						\
+	tracker-db-journal.h
 
 libtracker_db_la_LIBADD = 						\
 	$(top_builddir)/src/libtracker-common/libtracker-common.la	\
diff --git a/src/libtracker-db/tracker-db-backup.c b/src/libtracker-db/tracker-db-backup.c
new file mode 100644
index 0000000..e278eef
--- /dev/null
+++ b/src/libtracker-db/tracker-db-backup.c
@@ -0,0 +1,269 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <sqlite3.h>
+
+#include <libtracker-common/tracker-ontology.h>
+#include <libtracker-db/tracker-db-manager.h>
+#include <libtracker-db/tracker-db-interface-sqlite.h>
+
+#include "tracker-db-backup.h"
+
+#define TRACKER_DB_BACKUP_META_FILENAME_T	"meta-backup.db.tmp"
+
+typedef struct {
+	TrackerDBBackupFinished callback;
+	GDestroyNotify destroy;
+	gpointer user_data;
+	GError *error;
+	sqlite3_stmt *stmt;
+	sqlite3 *db, *backup_temp;
+	sqlite3_backup *backup_db;
+	gchar *backup_fname;
+	int result;
+	GFile *parent;
+} BackupInfo;
+
+GQuark
+tracker_db_backup_error_quark (void)
+{
+	return g_quark_from_static_string ("tracker-db-backup-error-quark");
+}
+
+static gboolean
+perform_callback (gpointer user_data)
+{
+	BackupInfo *info = user_data;
+
+	if (info->callback) {
+		info->callback (info->error, info->user_data);
+	}
+
+	return FALSE;
+}
+
+static void
+backup_info_free (gpointer user_data)
+{
+	BackupInfo *info = user_data;
+
+	if (info->parent) {
+		g_object_unref (info->parent);
+	}
+
+	if (info->destroy) {
+		info->destroy (info->user_data);
+	}
+
+	g_clear_error (&info->error);
+
+	if (info->stmt) {
+		sqlite3_finalize (info->stmt);
+	}
+
+	if (info->backup_db) {
+		sqlite3_backup_finish (info->backup_db);
+		info->backup_db = NULL;
+	}
+
+	if (info->backup_temp) {
+		sqlite3_close (info->backup_temp);
+	}
+
+	if (info->db) {
+		sqlite3_close (info->db);
+	}
+
+	if (info->backup_fname) {
+		g_free (info->backup_fname);
+	}
+
+	g_free (info);
+}
+
+
+static gboolean
+backup_file_step (gpointer user_data)
+{
+	BackupInfo *info = user_data;
+	guint cnt = 0;
+	gboolean cont = TRUE;
+
+	while (cont && info->result == SQLITE_OK) {
+
+		info->result = sqlite3_backup_step(info->backup_db, 5);
+
+		switch (info->result) {
+			case SQLITE_OK:
+			break;
+
+			case SQLITE_ERROR:
+			default:
+			cont = FALSE;
+			break;
+		}
+
+		if (cnt > 100) {
+			break;
+		}
+
+		cnt++;
+	}
+
+	return cont;
+}
+
+static void
+on_backup_temp_finished (gpointer user_data)
+{
+	BackupInfo *info = user_data;
+
+	if (info->backup_db) {
+		sqlite3_backup_finish (info->backup_db);
+		info->backup_db = NULL;
+	}
+
+	if (info->db) {
+		sqlite3_close (info->db);
+		info->db = NULL;
+	}
+
+
+	if (!info->error && info->result != SQLITE_DONE) {
+		g_set_error (&info->error, TRACKER_DB_BACKUP_ERROR, 
+		             TRACKER_DB_BACKUP_ERROR_UNKNOWN,
+		             "%s", sqlite3_errmsg (info->backup_temp));
+	}
+
+	if (!info->error) {
+		GFile *from_file, *to_file;
+
+		from_file = g_file_get_child (info->parent, TRACKER_DB_BACKUP_META_FILENAME_T);
+		to_file = g_file_get_child (info->parent, TRACKER_DB_BACKUP_META_FILENAME);
+
+		g_file_move (from_file, to_file, 
+			     G_FILE_COPY_OVERWRITE, 
+			     NULL, NULL, NULL,
+			     &info->error);
+
+		g_object_unref (from_file);
+		g_object_unref (to_file);
+	}
+
+	perform_callback (info);
+
+	backup_info_free (info);
+
+	return;
+}
+
+GFile *
+tracker_db_backup_file (GFile **parent_out, const gchar *type)
+{
+	GFile *file, *parent;
+	gchar *parent_path;
+
+	parent_path = g_build_filename (g_get_user_data_dir (),
+	                                "tracker",
+	                                "data",
+	                                NULL);
+
+	parent = g_file_new_for_path (parent_path);
+	file = g_file_get_child (parent, type);
+
+	if (parent_out) {
+		*parent_out = parent;
+	} else {
+		g_object_unref (parent);
+	}
+
+	g_free (parent_path);
+
+	return file;
+}
+
+
+void
+tracker_db_backup_save (TrackerDBBackupFinished callback,
+                        gpointer user_data,
+                        GDestroyNotify destroy)
+{
+	const gchar *db_file = tracker_db_manager_get_file (TRACKER_DB_METADATA);
+	BackupInfo *info = g_new0 (BackupInfo, 1);
+	GFile *file;
+
+	/* This procedure makes a meta-backup.db using sqlite3_backup API */
+
+	info->callback = callback;
+	info->user_data = user_data;
+	info->destroy = destroy;
+
+	file = tracker_db_backup_file (&info->parent, TRACKER_DB_BACKUP_META_FILENAME_T);
+	info->backup_fname = g_file_get_path (file);
+	g_object_unref (file);
+
+	if (sqlite3_open_v2 (db_file, &info->db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) {
+		g_set_error (&info->error, TRACKER_DB_BACKUP_ERROR, TRACKER_DB_BACKUP_ERROR_UNKNOWN,
+		             "Could not open sqlite3 database:'%s'", db_file);
+
+		g_idle_add_full (G_PRIORITY_DEFAULT, perform_callback, info, 
+		                 backup_info_free);
+
+		return;
+	}
+
+	if (sqlite3_open (info->backup_fname, &info->backup_temp) != SQLITE_OK) {
+		g_set_error (&info->error, TRACKER_DB_BACKUP_ERROR, TRACKER_DB_BACKUP_ERROR_UNKNOWN,
+		             "Could not open sqlite3 database:'%s'", info->backup_fname);
+
+		g_idle_add_full (G_PRIORITY_DEFAULT, perform_callback, info, 
+		                 backup_info_free);
+
+		return;
+	}
+
+	info->backup_db = sqlite3_backup_init (info->backup_temp, "main", 
+	                                       info->db, "main");
+
+	if (!info->backup_db) {
+		g_set_error (&info->error, TRACKER_DB_BACKUP_ERROR, TRACKER_DB_BACKUP_ERROR_UNKNOWN,
+		             "Unknown error creating backup db: '%s'", info->backup_fname);
+
+		g_idle_add_full (G_PRIORITY_DEFAULT, perform_callback, info, 
+		                 backup_info_free);
+
+		return;
+	}
+
+	g_idle_add_full (G_PRIORITY_DEFAULT, backup_file_step, info, 
+	                 on_backup_temp_finished);
+}
+
+
+
+
diff --git a/src/libtracker-db/tracker-db-backup.h b/src/libtracker-db/tracker-db-backup.h
new file mode 100644
index 0000000..1769f96
--- /dev/null
+++ b/src/libtracker-db/tracker-db-backup.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef __TRACKER_DB_BACKUP_H__
+#define __TRACKER_DB_BACKUP_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define TRACKER_DB_BACKUP_META_FILENAME		"meta-backup.db"
+
+G_BEGIN_DECLS
+
+#define TRACKER_DB_BACKUP_ERROR	    (tracker_db_backup_error_quark ())
+
+typedef enum {
+	TRACKER_DB_BACKUP_ERROR_UNKNOWN,
+} TrackerDBBackupError;
+
+typedef void (*TrackerDBBackupFinished)   (GError *error, gpointer user_data);
+
+GQuark    tracker_db_backup_error_quark (void);
+
+void      tracker_db_backup_save        (TrackerDBBackupFinished callback,
+                                         gpointer user_data,
+                                         GDestroyNotify destroy);
+GFile *   tracker_db_backup_file        (GFile **parent_out, 
+                                         const gchar *type);
+
+G_END_DECLS
+
+#endif /* __TRACKER_DB_BACKUP_H__ */
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.c b/src/libtracker-db/tracker-db-interface-sqlite.c
index ac869a3..921f3c0 100644
--- a/src/libtracker-db/tracker-db-interface-sqlite.c
+++ b/src/libtracker-db/tracker-db-interface-sqlite.c
@@ -21,8 +21,10 @@
 #include "config.h"
 
 #include <glib/gstdio.h>
+
 #include <sqlite3.h>
 #include <stdlib.h>
+#include <libtracker-common/tracker-common.h>
 
 #include <tracker-fts/tracker-fts.h>
 
@@ -71,6 +73,8 @@ struct SqliteAggregateData {
 
 static void tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface);
 static void tracker_db_statement_sqlite_iface_init (TrackerDBStatementIface *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);
@@ -97,20 +101,12 @@ tracker_db_interface_sqlite_enable_shared_cache (void)
   sqlite3_enable_shared_cache (1);
 }
 
-static GObject *
-tracker_db_interface_sqlite_constructor (GType			type,
-					 guint			n_construct_properties,
-					 GObjectConstructParam *construct_params)
+static void
+open_database (TrackerDBInterfaceSqlitePrivate *priv)
 {
-	GObject *object;
-	TrackerDBInterfaceSqlitePrivate *priv;
 	gchar *err_msg = NULL;
 	const gchar *env_path;
 
-	object = (* G_OBJECT_CLASS (tracker_db_interface_sqlite_parent_class)->constructor) (type,
-											     n_construct_properties,
-											     construct_params);
-	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (object);
 	g_assert (priv->filename != NULL);
 
 	if (!priv->ro) {
@@ -135,6 +131,22 @@ tracker_db_interface_sqlite_constructor (GType			type,
 	} else {
 		g_message ("Initialized tracker fts extension");
 	}
+}
+
+static GObject *
+tracker_db_interface_sqlite_constructor (GType			type,
+					 guint			n_construct_properties,
+					 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	TrackerDBInterfaceSqlitePrivate *priv;
+
+	object = (* G_OBJECT_CLASS (tracker_db_interface_sqlite_parent_class)->constructor) (type,
+											     n_construct_properties,
+											     construct_params);
+	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (object);
+
+	open_database (priv);
 
 	return object;
 }
@@ -190,23 +202,31 @@ tracker_db_interface_sqlite_get_property (GObject    *object,
 }
 
 static void
-tracker_db_interface_sqlite_finalize (GObject *object)
+close_database (TrackerDBInterfaceSqlitePrivate *priv)
 {
-	TrackerDBInterfaceSqlitePrivate *priv;
-
-	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (object);
-
 	g_hash_table_destroy (priv->dynamic_statements);
-
 	g_hash_table_destroy (priv->statements);
 
 	g_slist_foreach (priv->function_data, (GFunc) g_free, NULL);
 	g_slist_free (priv->function_data);
+	priv->function_data = NULL;
 
 	g_slist_foreach (priv->aggregate_data, (GFunc) g_free, NULL);
 	g_slist_free (priv->aggregate_data);
+	priv->aggregate_data = NULL;
 
 	sqlite3_close (priv->db);
+}
+
+static void
+tracker_db_interface_sqlite_finalize (GObject *object)
+{
+	TrackerDBInterfaceSqlitePrivate *priv;
+
+	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (object);
+
+	close_database (priv);
+
 	g_message ("Closed sqlite3 database:'%s'", priv->filename);
 
 	g_free (priv->filename);
@@ -249,19 +269,26 @@ tracker_db_interface_sqlite_class_init (TrackerDBInterfaceSqliteClass *class)
 }
 
 static void
-tracker_db_interface_sqlite_init (TrackerDBInterfaceSqlite *db_interface)
+prepare_database (TrackerDBInterfaceSqlitePrivate *priv)
 {
-	TrackerDBInterfaceSqlitePrivate *priv;
-
-	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
-
-	priv->ro = FALSE;
 	priv->dynamic_statements = g_hash_table_new_full (g_str_hash, g_str_equal,
 							  (GDestroyNotify) g_free,
 							  (GDestroyNotify) g_object_unref);
 	priv->statements = g_hash_table_new_full (g_str_hash, g_str_equal,
 						  (GDestroyNotify) g_free,
 						  (GDestroyNotify) sqlite3_finalize);
+
+}
+
+static void
+tracker_db_interface_sqlite_init (TrackerDBInterfaceSqlite *db_interface)
+{
+	TrackerDBInterfaceSqlitePrivate *priv;
+
+	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
+
+	priv->ro = FALSE;
+	prepare_database (priv);
 }
 
 static void
@@ -586,17 +613,19 @@ create_result_set_from_stmt (TrackerDBInterfaceSqlite  *interface,
 		if (sqlite3_errcode (priv->db) == SQLITE_IOERR ||
 		    sqlite3_errcode (priv->db) == SQLITE_CORRUPT ||
 		    sqlite3_errcode (priv->db) == SQLITE_NOTADB) {
+
 			sqlite3_finalize (stmt);
 			sqlite3_close (priv->db);
-			
+
 			g_unlink (priv->filename);
-			
+
 			g_error ("SQLite experienced an error with file:'%s'. "
 				 "It is either NOT a SQLite database or it is "
 				 "corrupt or there was an IO error accessing the data. "
 				 "This file has now been removed and will be recreated on the next start. "
 				 "Shutting down now.",
 				 priv->filename);
+
 			return NULL;
 		}
 
@@ -666,6 +695,8 @@ 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 *
@@ -864,6 +895,27 @@ tracker_db_statement_sqlite_bind_text (TrackerDBStatement	 *stmt,
 	sqlite3_bind_text (priv->stmt, index + 1, value, -1, SQLITE_TRANSIENT);
 }
 
+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,
 				     GError			**error)
diff --git a/src/libtracker-db/tracker-db-interface.c b/src/libtracker-db/tracker-db-interface.c
index 5bcb2d4..4cc6df6 100644
--- a/src/libtracker-db/tracker-db-interface.c
+++ b/src/libtracker-db/tracker-db-interface.c
@@ -373,6 +373,24 @@ tracker_db_interface_end_transaction (TrackerDBInterface *interface)
 }
 
 void
+tracker_db_interface_disconnect (TrackerDBInterface  *interface)
+{
+	TrackerDBInterfaceIface *iface;
+	g_return_val_if_fail (TRACKER_IS_DB_INTERFACE (interface), NULL);
+	iface = TRACKER_DB_INTERFACE_GET_IFACE (interface);
+	iface->disconnect (interface);
+}
+
+void
+tracker_db_interface_reconnect (TrackerDBInterface  *interface)
+{
+	TrackerDBInterfaceIface *iface;
+	g_return_val_if_fail (TRACKER_IS_DB_INTERFACE (interface), NULL);
+	iface = TRACKER_DB_INTERFACE_GET_IFACE (interface);
+	iface->reconnect (interface);
+}
+
+void
 tracker_db_statement_bind_double (TrackerDBStatement	*stmt,
 				  int			 idx,
 				  double		 value)
diff --git a/src/libtracker-db/tracker-db-interface.h b/src/libtracker-db/tracker-db-interface.h
index 4ced292..3d2cde4 100644
--- a/src/libtracker-db/tracker-db-interface.h
+++ b/src/libtracker-db/tracker-db-interface.h
@@ -66,6 +66,8 @@ struct TrackerDBInterfaceIface {
 	TrackerDBResultSet * (* execute_query)	       (TrackerDBInterface  *interface,
 							GError		   **error,
 							const gchar	    *query);
+	void		     (* disconnect)	       (TrackerDBInterface  *interface);
+	void		     (* reconnect)	       (TrackerDBInterface  *interface);
 
 };
 
@@ -120,6 +122,8 @@ 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,
diff --git a/src/libtracker-db/tracker-db-journal.c b/src/libtracker-db/tracker-db-journal.c
new file mode 100644
index 0000000..fdcfa76
--- /dev/null
+++ b/src/libtracker-db/tracker-db-journal.c
@@ -0,0 +1,167 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+#include "config.h"
+
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "tracker-db-journal.h"
+
+static gchar *filename = NULL;
+static FILE *journal = NULL;
+static GMappedFile *mapped = NULL;
+static gsize current_size = 0;
+
+#define TRACKER_DB_JOURNAL_LOG_FILENAME		"log.sparql.txt"
+
+static void
+get_filename (void)
+{
+	if (!filename) {
+		filename = g_build_filename (g_get_user_data_dir (),
+		                             "tracker",
+		                             "data",
+		                             TRACKER_DB_JOURNAL_LOG_FILENAME,
+		                             NULL);
+	}
+}
+
+gsize
+tracker_db_journal_get_size (void)
+{
+	return current_size;
+}
+
+const gchar*
+tracker_db_journal_filename (void)
+{
+	get_filename ();
+	return (const gchar *) filename;
+}
+
+void
+tracker_db_journal_open (void)
+{
+	struct stat st;
+
+	get_filename ();
+
+	journal = fopen (filename, "a");
+
+	if (stat (filename, &st) == 0) {
+		current_size = (gsize) st.st_size;
+	}
+}
+
+void
+tracker_db_journal_log (const gchar *query)
+{
+	if (journal) {
+		size_t len = strlen (query);
+		write (fileno (journal), query, len);
+		write (fileno (journal), "\n\0", 2);
+		current_size += (len + 2);
+	}
+}
+
+void 
+tracker_db_journal_fsync (void)
+{
+	if (journal) {
+		fsync (fileno (journal));
+	}
+}
+
+void
+tracker_db_journal_truncate (void)
+{
+	if (journal) {
+		ftruncate(fileno (journal), 0);
+		current_size = 0;
+		fsync (fileno (journal));
+	}
+}
+
+void
+tracker_db_journal_close (void)
+{
+	if (journal) {
+		fclose (journal);
+		journal = NULL;
+	}
+
+	g_free (filename);
+	filename = NULL;
+}
+
+TrackerJournalContents*
+tracker_db_journal_get_contents (guint transaction_size)
+{
+	GPtrArray *lines;
+	gsize max_pos, next_len;
+	gchar *cur;
+
+	get_filename ();
+
+	if (!mapped) {
+		GError *error = NULL;
+
+		mapped = g_mapped_file_new (filename, FALSE, &error);
+
+		if (error) {
+			g_warning ("Journal read: %s", error->message);
+			g_clear_error (&error);
+			mapped = NULL;
+			return NULL;
+		}
+	}
+
+	lines = g_ptr_array_sized_new (transaction_size > 0 ? transaction_size : 2000);
+
+	cur = g_mapped_file_get_contents (mapped);
+	max_pos = (gsize) (cur + g_mapped_file_get_length (mapped));
+
+	while (((gsize)cur) < max_pos) {
+		next_len = strnlen (cur, max_pos - ((gsize)cur)) + 1;
+		g_ptr_array_add (lines, cur);
+		cur += next_len;
+	}
+
+	return (TrackerJournalContents *) lines;
+}
+
+void 
+tracker_db_journal_free_contents (TrackerJournalContents *contents)
+{
+	if (mapped) {
+		g_mapped_file_free (mapped);
+		mapped = NULL;
+	}
+
+	g_ptr_array_free ((GPtrArray *)contents, TRUE);
+}
diff --git a/src/libtracker-db/tracker-db-journal.h b/src/libtracker-db/tracker-db-journal.h
new file mode 100644
index 0000000..552aee3
--- /dev/null
+++ b/src/libtracker-db/tracker-db-journal.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef __TRACKER_DB_JOURNAL_H__
+#define __TRACKER_DB_JOURNAL_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define TRACKER_DB_JOURNAL_MAX_SIZE	52428800
+
+G_BEGIN_DECLS
+
+typedef GPtrArray TrackerJournalContents;
+
+const gchar* tracker_db_journal_filename (void);
+void tracker_db_journal_open (void);
+void tracker_db_journal_log (const gchar *query);
+void tracker_db_journal_truncate (void);
+void tracker_db_journal_close (void);
+TrackerJournalContents* tracker_db_journal_get_contents (guint transaction_size);
+void tracker_db_journal_free_contents (TrackerJournalContents *contents);
+void tracker_db_journal_fsync (void);
+gsize tracker_db_journal_get_size (void);
+
+G_END_DECLS
+
+#endif /* __TRACKER_DB_JOURNAL_H__ */
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index 0e709c8..32e078f 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -35,8 +35,10 @@
 #include <libtracker-common/tracker-type-utils.h>
 #include <libtracker-common/tracker-utils.h>
 
+#include "tracker-db-backup.h"
 #include "tracker-db-manager.h"
 #include "tracker-db-interface-sqlite.h"
+#include "tracker-db-interface.h"
 
 /* ZLib buffer settings */
 #define ZLIB_BUF_SIZE		      8192
@@ -152,6 +154,8 @@ 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;
@@ -656,7 +660,7 @@ db_set_params (TrackerDBInterface *iface,
 	       gint		   page_size,
 	       gboolean		   add_functions)
 {
-	tracker_db_interface_execute_query (iface, NULL, "PRAGMA synchronous = NORMAL;");
+	tracker_db_interface_execute_query (iface, NULL, "PRAGMA synchronous = OFF;");
 	tracker_db_interface_execute_query (iface, NULL, "PRAGMA count_changes = 0;");
 	tracker_db_interface_execute_query (iface, NULL, "PRAGMA temp_store = FILE;");
 	tracker_db_interface_execute_query (iface, NULL, "PRAGMA encoding = \"UTF-8\"");
@@ -861,7 +865,7 @@ db_interface_create (TrackerDB db)
 }
 
 static void
-db_manager_remove_all (void)
+db_manager_remove_all (gboolean rm_backup_and_log, gboolean not_meta)
 {
 	guint i;
 
@@ -871,10 +875,34 @@ db_manager_remove_all (void)
 	 * calculate the absolute directories here. 
 	 */
 	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+
+		if (not_meta && i == TRACKER_DB_METADATA) {
+			continue;
+		}
+
 		g_message ("  Removing database:'%s'",
 			   dbs[i].abs_filename);
 		g_unlink (dbs[i].abs_filename);
 	}
+
+	if (rm_backup_and_log) {
+		GFile *file;
+		gchar *path;
+
+		file = tracker_db_backup_file (NULL, TRACKER_DB_BACKUP_META_FILENAME);
+		path = g_file_get_path (file);
+		g_message ("  Removing database:'%s'",
+			   path);
+		g_free (path);
+		g_file_delete (file, NULL, NULL);
+		g_object_unref (file);
+		path = tracker_db_journal_filename ();
+		g_message ("  Removing database:'%s'",
+			   path);
+		file = g_file_new_for_path (path);
+		g_file_delete (file, NULL, NULL);
+		g_object_unref (file);
+	}
 }
 
 static TrackerDBVersion
@@ -1016,17 +1044,78 @@ tracker_db_manager_ensure_locale (void)
 	g_free (stored_locale);
 }
 
+static gboolean
+check_meta_backup (gboolean *did_copy)
+{
+	const gchar *meta_filename;
+	gboolean retval = FALSE;
+
+	/* This is currently the only test for need_journal. We should add a
+	 * couple tests that test meta.db against consistenty, and if not
+	 * good, copy meta-backup.db over and set need_journal (being less 
+	 * conservative about using the backup, and not trusting the meta.db
+	 * as much as we do right now) */
+
+	meta_filename = dbs[TRACKER_DB_METADATA].abs_filename;
+
+	if (meta_filename) {
+		GFile *file;
+
+		file = g_file_new_for_path (meta_filename);
+
+		/* (more) Checks for a healthy meta.db should happen here */
+
+		if (!g_file_query_exists (file, NULL)) {
+			GFile *backup;
+
+			backup = tracker_db_backup_file (NULL, TRACKER_DB_BACKUP_META_FILENAME);
+
+			if (g_file_query_exists (backup, NULL)) {
+				GError *error = NULL;
+
+				/* Note that we leave meta-backup.db as is, it'll
+				 * be overwritten first-next time tracker-store.c's
+				 * sync_idle_handler will instruct this. */
+
+				g_file_copy (backup, file, G_FILE_COPY_OVERWRITE,
+				             NULL, NULL, NULL, &error);
+
+				if (!error && did_copy) {
+					*did_copy = TRUE;
+				}
+
+				g_clear_error (&error);
+			}
+
+			/* We always play the journal in case meta.db wasn't
+			 * healthy. Also if meta-backup.db didn't exist: that
+			 * just means that tracker-store.c's sync_idle_handler
+			 * didn't yet ran (meanwhile a first log-file is yet
+			 * already being made) */
+
+			retval = TRUE;
+
+			g_object_unref (backup);
+		}
+
+		g_object_unref (file);
+	}
+
+	return retval;
+}
+
 gboolean
 tracker_db_manager_init (TrackerDBManagerFlags	flags,
 			 gboolean	       *first_time,
-			 gboolean	        shared_cache)
+			 gboolean	        shared_cache,
+			 gboolean	       *need_journal)
 {
 	GType		    etype;
 	TrackerDBVersion    version;
 	gchar		   *filename;
 	const gchar	   *dir;
 	const gchar        *env_path;
-	gboolean	    need_reindex;
+	gboolean	    need_reindex, did_copy = FALSE;
 	guint		    i;
 
 	if (first_time) {
@@ -1126,6 +1215,13 @@ tracker_db_manager_init (TrackerDBManagerFlags	flags,
 		}
 	}
 
+	if (need_journal) {
+		/* That did_copy is used for called db_manager_remove_all, we
+		 * don't want it to also remove our freshly copied meta.db file. */
+
+		*need_journal = check_meta_backup (&did_copy);
+	}
+
 	/* If we are just initializing to remove the databases,
 	 * return here. 
 	 */
@@ -1158,11 +1254,15 @@ tracker_db_manager_init (TrackerDBManagerFlags	flags,
 		 * will cause errors and do nothing.
 		 */
 		g_message ("Cleaning up database files for reindex");
-		db_manager_remove_all ();
+
+		/* Remove all but the meta.db in case of did_copy, else remove
+		 * all (only in case meta-backup.db was not restored) */
+
+		db_manager_remove_all (FALSE, did_copy);
 
 		/* In cases where we re-init this module, make sure
 		 * we have cleaned up the ontology before we load all
-		 * new databases.
+		* new databases.
 		 */
 		tracker_ontology_shutdown ();
 
@@ -1214,9 +1314,58 @@ tracker_db_manager_init (TrackerDBManagerFlags	flags,
 								    TRACKER_DB_CONTENTS,
 								    TRACKER_DB_COMMON);
 	}
+
 	return TRUE;
 }
 
+void 
+tracker_db_manager_disconnect (void)
+{
+	if (resources_iface) {
+		guint i;
+ 		TrackerDB attachments[3] = { TRACKER_DB_FULLTEXT,
+					     TRACKER_DB_CONTENTS,
+					     TRACKER_DB_COMMON };
+
+		for (i = 0; i < 3; 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[3] = { TRACKER_DB_FULLTEXT,
+					     TRACKER_DB_CONTENTS,
+					     TRACKER_DB_COMMON };
+
+		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 < 3; 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)
 {
@@ -1268,11 +1417,11 @@ tracker_db_manager_shutdown (void)
 }
 
 void
-tracker_db_manager_remove_all (void)
+tracker_db_manager_remove_all (gboolean rm_backup_and_log)
 {
 	g_return_if_fail (initialized != FALSE);
 	
-	db_manager_remove_all ();
+	db_manager_remove_all (rm_backup_and_log, FALSE);
 }
 
 void
@@ -1327,7 +1476,7 @@ tracker_db_manager_get_file (TrackerDB db)
  *
  * returns: (caller-owns): a database connection
  **/
-TrackerDBInterface *
+static TrackerDBInterface *
 tracker_db_manager_get_db_interfaces (gint num, ...)
 {
 	gint		    n_args;
@@ -1361,7 +1510,7 @@ tracker_db_manager_get_db_interfaces (gint num, ...)
 	return connection;
 }
 
-TrackerDBInterface *
+static TrackerDBInterface *
 tracker_db_manager_get_db_interfaces_ro (gint num, ...)
 {
 	gint		    n_args;
diff --git a/src/libtracker-db/tracker-db-manager.h b/src/libtracker-db/tracker-db-manager.h
index d7701ba..95f0dd4 100644
--- a/src/libtracker-db/tracker-db-manager.h
+++ b/src/libtracker-db/tracker-db-manager.h
@@ -49,19 +49,20 @@ GType	     tracker_db_get_type			    (void) G_GNUC_CONST;
 
 gboolean     tracker_db_manager_init			    (TrackerDBManagerFlags  flags,
 							     gboolean		   *first_time,
-							     gboolean 		    shared_cache);
+							     gboolean 		    shared_cache,
+							     gboolean		   *need_journal);
 void	     tracker_db_manager_shutdown		    (void);
 
-void	     tracker_db_manager_remove_all		    (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);
-TrackerDBInterface *
-	     tracker_db_manager_get_db_interfaces	    (gint num, ...);
-TrackerDBInterface *
-	     tracker_db_manager_get_db_interfaces_ro	    (gint num, ...);
+
+void         tracker_db_manager_disconnect		    (void);
+void         tracker_db_manager_reconnect		    (void);
 
 G_END_DECLS
 
diff --git a/src/tracker-store/tracker-backup.c b/src/tracker-store/tracker-backup.c
index f2b7d36..50d7f67 100644
--- a/src/tracker-store/tracker-backup.c
+++ b/src/tracker-store/tracker-backup.c
@@ -35,6 +35,8 @@
 typedef struct {
 	DBusGMethodInvocation *context;
 	guint request_id;
+	gboolean play_journal;
+	GFile *destination, *journal;
 } TrackerDBusMethodInfo;
 
 G_DEFINE_TYPE (TrackerBackup, tracker_backup, G_TYPE_OBJECT)
@@ -58,7 +60,17 @@ tracker_backup_new (void)
 static void
 destroy_method_info (gpointer user_data)
 {
-	g_slice_free (TrackerDBusMethodInfo, user_data);
+	TrackerDBusMethodInfo *info = user_data;
+
+	if (info->destination) {
+		g_object_unref (info->destination);
+	}
+
+	if (info->journal) {
+		g_object_unref (info->journal);
+	}
+
+	g_free (info);
 }
 
 static void
@@ -74,81 +86,99 @@ backup_callback (GError *error, gpointer user_data)
 		return;
 	}
 
+	if (info->play_journal) {
+		tracker_store_play_journal ();
+	}
+
 	dbus_g_method_return (info->context);
 
 	tracker_dbus_request_success (info->request_id);
 }
 
+static void
+on_batch_commit (gpointer user_data)
+{
+	TrackerDBusMethodInfo *info = user_data;
+
+	/* At this point no transactions are left open, we can now start the
+	 * sqlite3_backup API, which will run itself as a GSource within the
+	 * mainloop after it got initialized (which will reopen the mainloop) */
+
+	tracker_data_backup_save (info->destination, info->journal,
+	                          backup_callback,
+	                          info, destroy_method_info);
+}
+
 void
 tracker_backup_save (TrackerBackup          *object,
-                     const gchar            *uri,
+                     const gchar            *destination_uri,
+                     const gchar            *journal_uri,
                      DBusGMethodInvocation  *context,
                      GError                **error)
 {
 	guint request_id;
 	TrackerDBusMethodInfo *info;
-	GFile *file;
 
 	request_id = tracker_dbus_get_next_request_id ();
 
 	tracker_dbus_request_new (request_id,
 	                          "DBus request to save backup into '%s'",
-	                          uri);
-
-	/* Previous DBus API accepted paths. For this reason I decided to try
-	 * to support both paths and uris. Perhaps we should just remove the
-	 * support for paths here? */
-
-	if (!strchr (uri, ':')) {
-		file = g_file_new_for_path (uri);
-	} else {
-		file = g_file_new_for_uri (uri);
-	}
+	                          destination_uri);
 
-	info = g_slice_new (TrackerDBusMethodInfo);
+	info = g_new0 (TrackerDBusMethodInfo, 1);
 
 	info->request_id = request_id;
 	info->context = context;
+	info->play_journal = FALSE;
+	info->destination = g_file_new_for_uri (destination_uri);
+	info->journal = g_file_new_for_uri (journal_uri);
 
-	tracker_data_backup_save (file, backup_callback,
-	                          info, destroy_method_info);
+	/* The sqlite3_backup API apparently doesn't much like open transactions,
+	 * this queue_commit will first call the currently open transaction
+	 * of the open batch (if any), and then in the callback we'll idd 
+	 * continue with making the backup itself (using sqlite3_backup's API) */
 
-	g_object_unref (file);
+	tracker_store_queue_commit (on_batch_commit, info, NULL);
 }
 
 void
 tracker_backup_restore (TrackerBackup          *object,
-                        const gchar            *uri,
+                        const gchar            *backup_uri,
+                        const gchar            *journal_uri,
                         DBusGMethodInvocation  *context,
                         GError                **error)
 {
 	guint request_id;
 	TrackerDBusMethodInfo *info;
-	GFile *file;
+	GFile *destination, *journal;
 
 	request_id = tracker_dbus_get_next_request_id ();
 
 	tracker_dbus_request_new (request_id,
 	                          "DBus request to restore backup from '%s'",
-	                          uri);
-
-	/* Previous DBus API accepted paths. For this reason I decided to try
-	 * to support both paths and uris. Perhaps we should just remove the
-	 * support for paths here? */
+	                          backup_uri);
 
-	if (!strchr (uri, ':')) {
-		file = g_file_new_for_path (uri);
-	} else {
-		file = g_file_new_for_uri (uri);
-	}
+	destination = g_file_new_for_uri (backup_uri);
+	journal = g_file_new_for_uri (journal_uri);
 
-	info = g_slice_new (TrackerDBusMethodInfo);
+	info = g_new0 (TrackerDBusMethodInfo, 1);
 
 	info->request_id = request_id;
 	info->context = context;
+	info->play_journal = TRUE;
+
+	/* This call is mostly synchronous, because we want to block the 
+	 * mainloop during a restore procedure (you're switching the active
+	 * database here, let's not allow queries during this time) 
+	 *
+	 * No need for commits or anything. Whatever is in the current db will
+	 * be eliminated in favor of the data in `backup_uri` and `journal_uri`. */
 
-	tracker_store_queue_turtle_import (file, backup_callback,
-	                                   info, destroy_method_info);
+	tracker_data_backup_restore (destination, journal,
+	                             backup_callback,
+	                             info, destroy_method_info);
 
-	g_object_unref (file);
+	g_object_unref (destination);
+	g_object_unref (journal);
 }
+
diff --git a/src/tracker-store/tracker-backup.h b/src/tracker-store/tracker-backup.h
index 0b663b0..54b248a 100644
--- a/src/tracker-store/tracker-backup.h
+++ b/src/tracker-store/tracker-backup.h
@@ -53,11 +53,13 @@ GType	       tracker_backup_get_type		   (void) G_GNUC_CONST;
 TrackerBackup *tracker_backup_new		   (void);
 
 void           tracker_backup_save                 (TrackerBackup         *object,
-						    const gchar           *path,
+						    const gchar           *destination_uri,
+						    const gchar           *journal_uri,
 						    DBusGMethodInvocation *context,
 						    GError **error);
 void           tracker_backup_restore              (TrackerBackup         *object,
-						    const gchar           *path,
+						    const gchar           *backup_uri,
+						    const gchar           *journal_uri,
 						    DBusGMethodInvocation *context,
 						    GError **error);
 
diff --git a/src/tracker-store/tracker-main.c b/src/tracker-store/tracker-main.c
index 5421b06..d7750b6 100644
--- a/src/tracker-store/tracker-main.c
+++ b/src/tracker-store/tracker-main.c
@@ -491,7 +491,7 @@ shutdown_directories (void)
 
 	/* If we are reindexing, just remove the databases */
 	if (private->reindex_on_shutdown) {
-		tracker_db_manager_remove_all ();
+		tracker_db_manager_remove_all (FALSE);
 	}
 }
 
@@ -644,7 +644,7 @@ main (gint argc, gchar *argv[])
 	TrackerPower		   *hal_power;
 	TrackerStorage		   *hal_storage;
 	TrackerDBManagerFlags	    flags = 0;
-	gboolean		    is_first_time_index;
+	gboolean		    is_first_time_index, need_journal = FALSE;
 
 	g_type_init ();
 
@@ -746,8 +746,6 @@ main (gint argc, gchar *argv[])
 			  NULL);
 #endif /* HAVE_HAL */
 
-	tracker_store_init ();
-
 	flags |= TRACKER_DB_MANAGER_REMOVE_CACHE;
 
 	if (force_reindex) {
@@ -761,10 +759,13 @@ main (gint argc, gchar *argv[])
 		flags |= TRACKER_DB_MANAGER_LOW_MEMORY_MODE;
 	}
 
-	if (!tracker_data_manager_init (flags, NULL, &is_first_time_index)) {
+	if (!tracker_data_manager_init (flags, NULL, &is_first_time_index, 
+	                                &need_journal)) {
 		return EXIT_FAILURE;
 	}
 
+	tracker_store_init (need_journal);
+
 #ifdef HAVE_HAL
 	/* We set up the mount points here. For the mount points, this
 	 * means contacting the Indexer. This means that we have to
diff --git a/src/tracker-store/tracker-resources.c b/src/tracker-store/tracker-resources.c
index 52bb1ed..ebe985d 100644
--- a/src/tracker-store/tracker-resources.c
+++ b/src/tracker-store/tracker-resources.c
@@ -399,6 +399,10 @@ on_statements_committed (gpointer user_data)
 
 	priv = TRACKER_RESOURCES_GET_PRIVATE (user_data);
 
+	/* For more information about this call, look at the function end_batch
+	 * of tracker-store.c */
+	tracker_store_flush_journal ();
+
 	events = tracker_events_get_pending ();
 
 	if (events) {
diff --git a/src/tracker-store/tracker-store.c b/src/tracker-store/tracker-store.c
index a6838e3..78e638f 100644
--- a/src/tracker-store/tracker-store.c
+++ b/src/tracker-store/tracker-store.c
@@ -22,8 +22,15 @@
 
 #include "config.h"
 
+#include <unistd.h>
+#include <sys/types.h>
+
 #include <libtracker-common/tracker-dbus.h>
 #include <libtracker-db/tracker-db-dbus.h>
+#include <libtracker-db/tracker-db-backup.h>
+#include <libtracker-db/tracker-db-journal.h>
+#include <libtracker-db/tracker-db-interface-sqlite.h>
+#include <libtracker-db/tracker-db-journal.h>
 
 #include <libtracker-data/tracker-data-update.h>
 #include <libtracker-data/tracker-data-query.h>
@@ -31,14 +38,15 @@
 
 #include "tracker-store.h"
 
-#define TRACKER_STORE_TRANSACTION_MAX	4000
+#define TRACKER_STORE_TRANSACTION_MAX			4000		/* At commit is journal fsynced too */
+#define TRACKER_STORE_JOURNAL_TIMEOUT_BEFORE_BACKUP	(60 * 60 * 2)	/* Two hours before backup */
 
 typedef struct {
-	gboolean  have_handler;
-	gboolean  batch_mode;
+	gboolean  have_handler, have_sync_handler;
+	gboolean  batch_mode, start_log;
 	guint     batch_count;
 	GQueue   *queue;
-	guint     handler;
+	guint     handler, sync_handler;
 } TrackerStorePrivate;
 
 typedef enum {
@@ -145,11 +153,35 @@ end_batch (TrackerStorePrivate *private)
 	if (private->batch_mode) {
 		/* commit pending batch items */
 		tracker_data_commit_transaction ();
+
+		/* The on_statements_committed in tracker-resources.c performs
+		 * the flush on the journal, I can only register one callback 
+		 * for this atm, so that's why it's called over there as a 
+		 * tracker_store_flush_journal */
+
 		private->batch_mode = FALSE;
 		private->batch_count = 0;
 	}
 }
 
+static void
+on_backup_done (GError *error, gpointer user_data)
+{
+	if (!error) {
+		tracker_db_journal_truncate ();
+	}
+}
+
+static void
+log_to_journal (TrackerStorePrivate *private, const gchar *query)
+{
+	tracker_db_journal_log (query);
+
+	if (tracker_db_journal_get_size () > TRACKER_DB_JOURNAL_MAX_SIZE) {
+		tracker_db_backup_save (on_backup_done, NULL, NULL);
+	}
+}
+
 static gboolean
 queue_idle_handler (gpointer user_data)
 {
@@ -165,6 +197,11 @@ queue_idle_handler (gpointer user_data)
 		begin_batch (private);
 
 		tracker_data_update_sparql (task->data.query, &error);
+
+		if (private->start_log) {
+			log_to_journal (private, task->data.query);
+		}
+
 		if (!error) {
 			private->batch_count++;
 			if (private->batch_count >= TRACKER_STORE_TRANSACTION_MAX) {
@@ -235,6 +272,14 @@ queue_idle_handler (gpointer user_data)
 	return !g_queue_is_empty (private->queue);
 }
 
+static gboolean
+sync_idle_handler (gpointer user_data)
+{
+	tracker_db_backup_save (on_backup_done, NULL, NULL);
+
+	return TRUE;
+}
+
 static void
 queue_idle_destroy (gpointer user_data)
 {
@@ -243,8 +288,65 @@ queue_idle_destroy (gpointer user_data)
 	private->have_handler = FALSE;
 }
 
+
+static void
+sync_idle_destroy (gpointer user_data)
+{
+	TrackerStorePrivate *private = user_data;
+
+	tracker_db_journal_close ();
+
+	private->have_sync_handler = FALSE;
+}
+
+void 
+tracker_store_flush_journal (void)
+{
+	TrackerStorePrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	tracker_db_journal_fsync ();
+}
+
+static void
+internal_play_journal (TrackerStorePrivate *private)
+{
+	TrackerJournalContents *lines;
+
+	lines = tracker_db_journal_get_contents (TRACKER_STORE_TRANSACTION_MAX);
+
+	if (lines) {
+		guint i;
+
+		tracker_data_begin_transaction ();
+		private->start_log = FALSE;
+		for (i = 0; i < lines->len; i++) {
+			const gchar *line = g_ptr_array_index (lines, i);
+			tracker_store_sparql_update (line, NULL);
+		}
+		tracker_db_journal_truncate ();
+		private->start_log = TRUE;
+		tracker_data_commit_transaction ();
+
+		tracker_db_journal_free_contents (lines);
+	}
+}
+
+void
+tracker_store_play_journal (void)
+{
+	TrackerStorePrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	internal_play_journal (private);
+}
+
 void
-tracker_store_init (void)
+tracker_store_init (gboolean load_journal)
 {
 	TrackerStorePrivate *private;
 
@@ -255,6 +357,20 @@ tracker_store_init (void)
 	g_static_private_set (&private_key,
 	                      private,
 	                      private_free);
+
+	if (load_journal) {
+		internal_play_journal (private);
+	}
+
+	tracker_db_journal_open ();
+
+	private->start_log = TRUE;
+
+	private->sync_handler = g_timeout_add_seconds_full (G_PRIORITY_LOW,
+	                                                    TRACKER_STORE_JOURNAL_TIMEOUT_BEFORE_BACKUP,
+	                                                    sync_idle_handler,
+	                                                    private,
+	                                                    sync_idle_destroy);
 }
 
 void
@@ -270,6 +386,11 @@ tracker_store_shutdown (void)
 		private->have_handler = FALSE;
 	}
 
+	if (private->have_sync_handler) {
+		g_source_remove (private->sync_handler);
+		private->have_sync_handler = FALSE;
+	}
+
 	g_static_private_set (&private_key, NULL, NULL);
 }
 
@@ -384,6 +505,11 @@ tracker_store_sparql_update (const gchar *sparql,
 	}
 
 	tracker_data_update_sparql (sparql, error);
+
+	if (private->start_log) {
+		log_to_journal (private, sparql);
+	}
+
 }
 
 TrackerDBResultSet*
diff --git a/src/tracker-store/tracker-store.h b/src/tracker-store/tracker-store.h
index 27f7eb6..a87320a 100644
--- a/src/tracker-store/tracker-store.h
+++ b/src/tracker-store/tracker-store.h
@@ -36,7 +36,7 @@ typedef void (* TrackerStoreCommitCallback)        (gpointer         user_data);
 typedef void (* TrackerStoreTurtleCallback)        (GError          *error,
                                                     gpointer         user_data);
 
-void         tracker_store_init                   (void);
+void         tracker_store_init                   (gboolean load_journal);
 void         tracker_store_shutdown               (void);
 void         tracker_store_queue_commit           (TrackerStoreCommitCallback       callback,
                                                    gpointer       user_data,
@@ -63,6 +63,9 @@ TrackerDBResultSet*
 
 guint        tracker_store_get_queue_size         (void);
 
+void         tracker_store_play_journal           (void);
+void         tracker_store_flush_journal          (void);
+
 G_END_DECLS
 
 #endif /* __TRACKER_STORE_H__ */
diff --git a/src/tracker-utils/tracker-processes.c b/src/tracker-utils/tracker-processes.c
index 020e079..76f11ea 100644
--- a/src/tracker-utils/tracker-processes.c
+++ b/src/tracker-utils/tracker-processes.c
@@ -37,7 +37,7 @@
 
 static gboolean     should_kill;
 static gboolean     should_terminate;
-static gboolean     hard_reset;
+static gboolean     hard_reset, soft_reset;
 
 static GOptionEntry entries[] = {
 	{ "kill", 'k', 0, G_OPTION_ARG_NONE, &should_kill,
@@ -47,6 +47,9 @@ static GOptionEntry entries[] = {
 	  N_("Use SIGTERM to stop all tracker processes found"),
 	  NULL 
 	},
+	{ "soft-reset", 's', 0, G_OPTION_ARG_NONE, &soft_reset,
+	  N_("This will kill all Tracker processes and remove all databases except the backup and journal (a restart will restore the data)"),
+	  NULL },
 	{ "hard-reset", 'r', 0, G_OPTION_ARG_NONE, &hard_reset,
 	  N_("This will kill all Tracker processes and remove all databases"),
 	  NULL },
@@ -144,13 +147,13 @@ main (int argc, char **argv)
 		g_printerr ("%s\n",
 			    _("You can not use the --kill and --terminate arguments together"));
 		return EXIT_FAILURE;
-	} else if (hard_reset && should_terminate) {
+	} else if ((hard_reset || soft_reset) && should_terminate) {
 		g_printerr ("%s\n",
 			    _("You can not use the --terminate with --hard-reset, --kill is implied"));
 		return EXIT_FAILURE;
 	}
 
-	if (hard_reset) {
+	if (hard_reset || soft_reset) {
 		/* Imply --kill */
 		should_kill = TRUE;
 	}
@@ -235,7 +238,7 @@ main (int argc, char **argv)
 	g_slist_foreach (pids, (GFunc) g_free, NULL);
 	g_slist_free (pids);
 
-	if (hard_reset) {
+	if (hard_reset || soft_reset) {
 		guint log_handler_id;
 
 		/* Set log handler for library messages */
@@ -247,11 +250,11 @@ main (int argc, char **argv)
 		g_log_set_default_handler (log_handler, NULL);
 
 		/* Clean up */
-		if (!tracker_db_manager_init (TRACKER_DB_MANAGER_REMOVE_ALL, NULL, FALSE)) {
+		if (!tracker_db_manager_init (TRACKER_DB_MANAGER_REMOVE_ALL, NULL, FALSE, NULL)) {
 			return EXIT_FAILURE;
 		}
 
-		tracker_db_manager_remove_all ();
+		tracker_db_manager_remove_all (hard_reset);
 		tracker_db_manager_shutdown ();
 
 		/* Unset log handler */
diff --git a/tests/libtracker-data/tracker-ontology-test.c b/tests/libtracker-data/tracker-ontology-test.c
index def14d9..a75f352 100644
--- a/tests/libtracker-data/tracker-ontology-test.c
+++ b/tests/libtracker-data/tracker-ontology-test.c
@@ -94,7 +94,7 @@ test_query (gconstpointer test_data)
 	/* initialization */
 	tracker_data_manager_init (TRACKER_DB_MANAGER_FORCE_REINDEX,
 		                   NULL, 
-				   NULL);
+				   NULL, NULL);
 
 	/* load data set */
 	data_filename = g_strconcat (data_prefix, ".ttl", NULL);
diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c
index 28718f0..d9635ee 100644
--- a/tests/libtracker-data/tracker-sparql-test.c
+++ b/tests/libtracker-data/tracker-sparql-test.c
@@ -107,7 +107,7 @@ test_sparql_query (gconstpointer test_data)
 
 	tracker_data_manager_init (TRACKER_DB_MANAGER_FORCE_REINDEX,
 		                   data_prefix, 
-				   NULL);
+				   NULL, NULL);
 
 	/* data_path = g_build_path (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "libtracker-data", NULL); */
 



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