[tracker/urho-sync] Restoring the db using a backup on corruption



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

 src/libtracker-db/tracker-db-backup.c           |    3 +-
 src/libtracker-db/tracker-db-interface-sqlite.c |   25 +++++++++--
 src/libtracker-db/tracker-db-interface-sqlite.h |    3 +
 src/tracker-store/tracker-store.c               |   50 +++++++++++++++++++++--
 4 files changed, 72 insertions(+), 9 deletions(-)
---
diff --git a/src/libtracker-db/tracker-db-backup.c b/src/libtracker-db/tracker-db-backup.c
index a7246af..647995f 100644
--- a/src/libtracker-db/tracker-db-backup.c
+++ b/src/libtracker-db/tracker-db-backup.c
@@ -32,6 +32,7 @@
 
 #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"
 
@@ -189,7 +190,7 @@ tracker_db_backup_save (TrackerBackupFinished callback,
 	file = g_file_new_for_path (db_file);
 	parent = g_file_get_parent (file);
 	g_object_unref (file);
-	file = g_file_get_child (parent, "meta-backup.db");
+	file = g_file_get_child (parent, TRACKER_META_BACKUP_DB_FILENAME);
 	g_object_unref (parent);
 	info->backup_fname = g_file_get_path (file);
 	g_object_unref (file);
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.c b/src/libtracker-db/tracker-db-interface-sqlite.c
index 1c54761..7deab6a 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-db-interface-sqlite.h"
 
@@ -599,17 +601,32 @@ 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) {
+			GFile *orig, *file, *parent;
+
 			sqlite3_finalize (stmt);
 			sqlite3_close (priv->db);
-			
-			g_unlink (priv->filename);
-			
+
+			orig = g_file_new_for_path (priv->filename);
+			parent = g_file_get_parent (orig);
+			file = g_file_get_child (parent, TRACKER_META_BACKUP_DB_FILENAME);
+
+			if (g_file_query_exists (file, NULL)) {
+				g_file_copy (file, orig, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL);
+			} else {
+				g_file_delete (file, NULL, NULL);
+			}
+
+			g_object_unref (file);
+			g_object_unref (parent);
+			g_object_unref (file);
+
 			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. "
+				 "This file has now been replaced with the last known backup "
 				 "Shutting down now.",
 				 priv->filename);
+
 			return NULL;
 		}
 
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.h b/src/libtracker-db/tracker-db-interface-sqlite.h
index 8ef3ace..bd2e305 100644
--- a/src/libtracker-db/tracker-db-interface-sqlite.h
+++ b/src/libtracker-db/tracker-db-interface-sqlite.h
@@ -20,6 +20,9 @@
 #ifndef __TRACKER_DB_INTERFACE_SQLITE_H__
 #define __TRACKER_DB_INTERFACE_SQLITE_H__
 
+#define TRACKER_META_BACKUP_DB_FILENAME		"meta-backup.db"
+#define TRACKER_META_BACKUP_LOG_FILENAME	"log.sparql.txt"
+
 #include "tracker-db-interface.h"
 
 G_BEGIN_DECLS
diff --git a/src/tracker-store/tracker-store.c b/src/tracker-store/tracker-store.c
index d6c974d..d0a30de 100644
--- a/src/tracker-store/tracker-store.c
+++ b/src/tracker-store/tracker-store.c
@@ -28,6 +28,7 @@
 #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-interface-sqlite.h>
 
 #include <libtracker-data/tracker-data-update.h>
 #include <libtracker-data/tracker-data-query.h>
@@ -39,7 +40,7 @@
 
 typedef struct {
 	gboolean  have_handler, have_sync_handler;
-	gboolean  batch_mode;
+	gboolean  batch_mode, start_log;
 	guint     batch_count;
 	GQueue   *queue;
 	guint     handler, sync_handler;
@@ -180,7 +181,7 @@ queue_idle_handler (gpointer user_data)
 
 		tracker_data_update_sparql (task->data.query, &error);
 
-		if (journal) {
+		if (journal && private->start_log) {
 			write (fileno (journal), task->data.query, strlen (task->data.query));
 			write (fileno (journal), "\n", 1);
 			fsync (fileno (journal));
@@ -289,10 +290,34 @@ sync_idle_destroy (gpointer user_data)
 	private->have_sync_handler = FALSE;
 }
 
+static void
+on_committed (gpointer user_data)
+{
+	TrackerStorePrivate *private;
+
+	if (journal) {
+		ftruncate(fileno (journal), 0);
+	}
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	private->start_log = TRUE;
+}
+
+static void
+immediate_commit (GError *error, gpointer user_data)
+{
+	tracker_store_queue_commit (on_committed, NULL, NULL);
+}
+
 void
 tracker_store_init (void)
 {
 	TrackerStorePrivate *private;
+	gchar *filename;
+	gchar *lines = NULL;
+	gsize len;
 
 	private = g_new0 (TrackerStorePrivate, 1);
 
@@ -302,7 +327,24 @@ tracker_store_init (void)
 	                      private,
 	                      private_free);
 
-	journal = fopen ("/tmp/journal.sparql.txt", "w");
+	filename = g_build_filename (g_get_tmp_dir (), 
+	                             TRACKER_META_BACKUP_LOG_FILENAME, 
+	                             NULL);
+
+	g_file_get_contents (filename, &lines, &len, NULL);
+
+	journal = fopen (filename, "a");
+
+	if (lines) {
+		tracker_store_queue_sparql_update (lines,
+		                                   immediate_commit, 
+		                                   NULL, NULL);
+		g_free (lines);
+	} else {
+		private->start_log = TRUE;
+	}
+
+	g_free (filename);
 
 	if (journal) {
 		private->sync_handler = g_timeout_add_seconds_full (G_PRIORITY_LOW,
@@ -447,7 +489,7 @@ tracker_store_sparql_update (const gchar *sparql,
 
 	tracker_data_update_sparql (sparql, error);
 
-	if (journal) {
+	if (journal && private->start_log) {
 		write (fileno (journal), sparql, strlen (sparql));
 		write (fileno (journal), "\n", 1);
 



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