[tracker/binary-log] Checking databases for corruption



commit c523fa6513c463b21a0a3ea5970df64a8ebf2104
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Jan 6 18:02:37 2010 +0100

    Checking databases for corruption

 src/libtracker-data/tracker-data-manager.c        |    9 +-
 src/libtracker-data/tracker-data-manager.h        |    3 +-
 src/libtracker-db/tracker-db-manager.c            |  180 +++++++++++++++++----
 src/libtracker-db/tracker-db-manager.h            |    3 +-
 src/tracker-control/tracker-control.c             |    2 +-
 src/tracker-store/tracker-main.c                  |    7 +-
 tests/libtracker-data/tracker-ontology-test.c     |    2 +-
 tests/libtracker-data/tracker-sparql-blank-test.c |    2 +-
 tests/libtracker-data/tracker-sparql-test.c       |    2 +-
 tests/libtracker-fts/tracker-fts-test.c           |    2 +-
 10 files changed, 155 insertions(+), 57 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index a760728..16e3648 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -948,8 +948,7 @@ create_fts_table (TrackerDBInterface *iface)
 gboolean
 tracker_data_manager_init (TrackerDBManagerFlags  flags,
                            const gchar           *test_schema,
-                           gboolean              *first_time,
-                           gboolean              *need_journal)
+                           gboolean              *first_time)
 {
 	TrackerDBInterface *iface;
 	gboolean is_first_time_index, read_journal;
@@ -959,17 +958,13 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 		*first_time = FALSE;
 	}
 
-	if (need_journal) {
-		*need_journal = FALSE;
-	}
-
 	if (initialized) {
 		return TRUE;
 	}
 
 	read_journal = FALSE;
 
-	tracker_db_manager_init (flags, &is_first_time_index, FALSE, need_journal);
+	tracker_db_manager_init (flags, &is_first_time_index, FALSE);
 
 	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 d0ca752..5a976b6 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -39,8 +39,7 @@ G_BEGIN_DECLS
 
 gboolean tracker_data_manager_init                (TrackerDBManagerFlags  flags,
                                                    const gchar           *test_schema,
-                                                   gboolean              *first_time,
-                                                   gboolean              *need_journal);
+                                                   gboolean              *first_time);
 void     tracker_data_manager_shutdown            (void);
 gint64   tracker_data_manager_get_db_option_int64 (const gchar           *option);
 void     tracker_data_manager_set_db_option_int64 (const gchar           *option,
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index b76d521..5f3e443 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -25,6 +25,10 @@
 #include <zlib.h>
 #include <locale.h>
 #include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <fcntl.h>
 
 #include <glib/gstdio.h>
 
@@ -53,6 +57,8 @@
 #define TRACKER_DB_VERSION_NOW        TRACKER_DB_VERSION_8
 #define TRACKER_DB_VERSION_FILE       "db-version.txt"
 
+#define IN_USE_FILENAME               ".meta.isrunning"
+
 typedef enum {
 	TRACKER_DB_LOCATION_DATA_DIR,
 	TRACKER_DB_LOCATION_USER_DATA_DIR,
@@ -1009,12 +1015,49 @@ tracker_db_manager_ensure_locale (void)
 	g_free (stored_locale);
 }
 
+static void
+db_recreate_all (void)
+{
+	guint i;
+
+	/* We call an internal version of this function here
+	 * because at the time 'initialized' = FALSE and that
+	 * will cause errors and do nothing.
+	 */
+	g_message ("Cleaning up database files for reindex");
+
+	db_manager_remove_all (FALSE);
+
+	/* In cases where we re-init this module, make sure
+	 * we have cleaned up the ontology before we load all
+	 * new databases.
+	 */
+	tracker_ontology_shutdown ();
+
+	/* Make sure we initialize all other modules we depend on */
+	tracker_ontology_init ();
+
+	/* Now create the databases and close them */
+	g_message ("Creating database files, this may take a few moments...");
+
+	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+		dbs[i].iface = db_interface_create (i);
+	}
+
+	/* We don't close the dbs in the same loop as before
+	 * becase some databases need other databases
+	 * attached to be created correctly.
+	 */
+	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+		g_object_unref (dbs[i].iface);
+		dbs[i].iface = NULL;
+	}
+}
 
 gboolean
 tracker_db_manager_init (TrackerDBManagerFlags  flags,
                          gboolean              *first_time,
-                         gboolean               shared_cache,
-                         gboolean              *need_journal)
+                         gboolean               shared_cache)
 {
 	GType               etype;
 	TrackerDBVersion    version;
@@ -1023,16 +1066,14 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 	const gchar        *env_path;
 	gboolean            need_reindex;
 	guint               i;
+	gchar              *in_use_filename;
+	int                 in_use_file;
 
 	/* First set defaults for return values */
 	if (first_time) {
 		*first_time = FALSE;
 	}
 
-	if (need_journal) {
-		*need_journal = FALSE;
-	}
-
 	if (initialized) {
 		return TRUE;
 	}
@@ -1140,6 +1181,12 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 		tracker_db_interface_sqlite_enable_shared_cache ();
 	}
 
+	in_use_filename = g_build_filename (g_get_user_data_dir (),
+	                                    "tracker",
+	                                    "data",
+	                                    IN_USE_FILENAME,
+	                                    NULL);
+
 	/* Should we reindex? If so, just remove all databases files,
 	 * NOT the paths, note, that these paths are also used for
 	 * other things like the nfs lock file.
@@ -1153,51 +1200,103 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 			return FALSE;
 		}
 
-		/* We call an internal version of this function here
-		 * because at the time 'initialized' = FALSE and that
-		 * will cause errors and do nothing.
-		 */
-		g_message ("Cleaning up database files for reindex");
-
-		db_manager_remove_all (FALSE);
-
-		/* In cases where we re-init this module, make sure
-		 * we have cleaned up the ontology before we load all
-		 * new databases.
-		 */
-		tracker_ontology_shutdown ();
+		db_recreate_all ();
 
 		/* Make sure we initialize all other modules we depend on */
 		tracker_ontology_init ();
 
-		/* Now create the databases and close them */
-		g_message ("Creating database files, this may take a few moments...");
+		/* Load databases */
+		g_message ("Loading databases files...");
 
 		for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
 			dbs[i].iface = db_interface_create (i);
+			dbs[i].mtime = tracker_file_get_mtime (dbs[i].abs_filename);
 		}
 
-		/* We don't close the dbs in the same loop as before
-		 * becase some databases need other databases
-		 * attached to be created correctly.
-		 */
-		for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
-			g_object_unref (dbs[i].iface);
-			dbs[i].iface = NULL;
-		}
 	} else {
 		/* Make sure we initialize all other modules we depend on */
 		tracker_ontology_init ();
-	}
 
-	/* Load databases */
-	g_message ("Loading databases files...");
+		/* Load databases */
+		g_message ("Loading databases files...");
 
-	for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
-		dbs[i].iface = db_interface_create (i);
-		dbs[i].mtime = tracker_file_get_mtime (dbs[i].abs_filename);
+		if (g_file_test (in_use_filename, G_FILE_TEST_EXISTS)) {
+			gboolean must_recreate;
+			gsize size = 0;
+
+			must_recreate = FALSE;
+
+			g_message ("Didn't shut down cleanly last time, doing integrity checks");
+
+			for (i = 1; i < G_N_ELEMENTS (dbs) && !must_recreate; i++) {
+				TrackerDBCursor *cursor;
+				TrackerDBStatement *stmt;
+				struct stat st;
+
+				if (g_stat (dbs[i].abs_filename, &st) == 0) {
+					size = st.st_size;
+				}
+
+				/* Size is 1 when using echo > file.db, none of our databases
+				 * are only one byte in size even initually. */
+
+				if (size == 0 || size == 1) {
+					must_recreate = TRUE;
+					continue;
+				}
+
+				dbs[i].iface = db_interface_create (i);
+				dbs[i].mtime = tracker_file_get_mtime (dbs[i].abs_filename);
+
+				stmt = tracker_db_interface_create_statement (dbs[i].iface,
+															  "PRAGMA integrity_check(1)");
+
+				cursor = tracker_db_statement_start_cursor (stmt, NULL);
+				g_object_unref (stmt);
+
+				if (cursor) {
+					if (tracker_db_cursor_iter_next (cursor)) {
+						if (g_strcmp0 (tracker_db_cursor_get_string (cursor, 0), "ok") != 0) {
+							must_recreate = TRUE;
+						}
+					}
+					g_object_unref (cursor);
+				}
+			}
+
+			if (must_recreate) {
+
+				if (first_time) {
+					*first_time = TRUE;
+				}
+
+				for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+					if (dbs[i].iface)
+						g_object_unref (dbs[i].iface);
+				}
+
+				db_recreate_all ();
+
+				for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+					dbs[i].iface = db_interface_create (i);
+					dbs[i].mtime = tracker_file_get_mtime (dbs[i].abs_filename);
+				}
+			}
+		} else {
+			for (i = 1; i < G_N_ELEMENTS (dbs); i++) {
+				dbs[i].iface = db_interface_create (i);
+				dbs[i].mtime = tracker_file_get_mtime (dbs[i].abs_filename);
+			}
+		}
 	}
 
+	in_use_file = g_open (in_use_filename, 
+	                      O_WRONLY | O_APPEND | O_CREAT | O_SYNC,
+	                      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+	fsync (in_use_file);
+	close (in_use_file);
+	g_free (in_use_filename);
+
 	tracker_db_manager_ensure_locale ();
 
 	initialized = TRUE;
@@ -1267,6 +1366,7 @@ void
 tracker_db_manager_shutdown (void)
 {
 	guint i;
+	gchar *in_use_filename;
 
 	if (!initialized) {
 		return;
@@ -1311,6 +1411,16 @@ tracker_db_manager_shutdown (void)
 	tracker_ontology_shutdown ();
 
 	initialized = FALSE;
+
+	in_use_filename = g_build_filename (g_get_user_data_dir (),
+	                                    "tracker",
+	                                    "data",
+	                                    IN_USE_FILENAME,
+	                                    NULL);
+
+	g_unlink (in_use_filename);
+
+	g_free (in_use_filename);
 }
 
 void
diff --git a/src/libtracker-db/tracker-db-manager.h b/src/libtracker-db/tracker-db-manager.h
index c46dad6..f7c6636 100644
--- a/src/libtracker-db/tracker-db-manager.h
+++ b/src/libtracker-db/tracker-db-manager.h
@@ -50,8 +50,7 @@ typedef enum {
 GType               tracker_db_get_type                         (void) G_GNUC_CONST;
 gboolean            tracker_db_manager_init             (TrackerDBManagerFlags  flags,
                                                          gboolean              *first_time,
-                                                         gboolean               shared_cache,
-                                                         gboolean              *need_journal);
+                                                         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);
diff --git a/src/tracker-control/tracker-control.c b/src/tracker-control/tracker-control.c
index 337fbed..adcebf4 100644
--- a/src/tracker-control/tracker-control.c
+++ b/src/tracker-control/tracker-control.c
@@ -351,7 +351,7 @@ main (int argc, char **argv)
 		tracker_db_journal_init (NULL);
 
 		/* Clean up */
-		if (!tracker_db_manager_init (TRACKER_DB_MANAGER_REMOVE_ALL, NULL, FALSE, NULL)) {
+		if (!tracker_db_manager_init (TRACKER_DB_MANAGER_REMOVE_ALL, NULL, FALSE)) {
 			return EXIT_FAILURE;
 		}
 
diff --git a/src/tracker-store/tracker-main.c b/src/tracker-store/tracker-main.c
index 6af9255..dafc6a1 100644
--- a/src/tracker-store/tracker-main.c
+++ b/src/tracker-store/tracker-main.c
@@ -326,7 +326,6 @@ main (gint argc, gchar *argv[])
 	TrackerConfig *config;
 	TrackerDBManagerFlags flags = 0;
 	gboolean is_first_time_index;
-	gboolean need_journal;
 
 	g_type_init ();
 
@@ -430,14 +429,10 @@ main (gint argc, gchar *argv[])
 
 	if (!tracker_data_manager_init (flags,
 	                                NULL,
-	                                &is_first_time_index,
-	                                &need_journal)) {
+	                                &is_first_time_index)) {
 		return EXIT_FAILURE;
 	}
 
-	/* TODO binary-log: need_journal might contain whether the db was corrupt
-	 * or not Do something with that.*/
-
 	tracker_store_init ();
 
 	if (private->shutdown) {
diff --git a/tests/libtracker-data/tracker-ontology-test.c b/tests/libtracker-data/tracker-ontology-test.c
index 2110bd6..31233c8 100644
--- a/tests/libtracker-data/tracker-ontology-test.c
+++ b/tests/libtracker-data/tracker-ontology-test.c
@@ -95,7 +95,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-blank-test.c b/tests/libtracker-data/tracker-sparql-blank-test.c
index 7788290..bc6a364 100644
--- a/tests/libtracker-data/tracker-sparql-blank-test.c
+++ b/tests/libtracker-data/tracker-sparql-blank-test.c
@@ -43,7 +43,7 @@ test_blank (void)
 	/* initialization */
 	tracker_data_manager_init (TRACKER_DB_MANAGER_FORCE_REINDEX,
 	                           NULL,
-	                           NULL, NULL);
+	                           NULL);
 
 	/* perform update in transaction */
 
diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c
index 563b671..18d1f88 100644
--- a/tests/libtracker-data/tracker-sparql-test.c
+++ b/tests/libtracker-data/tracker-sparql-test.c
@@ -116,7 +116,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); */
 
diff --git a/tests/libtracker-fts/tracker-fts-test.c b/tests/libtracker-fts/tracker-fts-test.c
index a39fabc..777ae6e 100644
--- a/tests/libtracker-fts/tracker-fts-test.c
+++ b/tests/libtracker-fts/tracker-fts-test.c
@@ -70,7 +70,7 @@ test_sparql_query (gconstpointer test_data)
 
 	tracker_data_manager_init (TRACKER_DB_MANAGER_FORCE_REINDEX,
 	                           data_prefix,
-	                           NULL, NULL);
+	                           NULL);
 
 	/* load data / perform updates */
 



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