[tracker/binary-log-2: 6/38] libtracker-db: Improve the journal API



commit be45d40696743b94566db4cd930ef0431171dda7
Author: Martyn Russell <martyn lanedo com>
Date:   Mon Jan 4 14:33:59 2010 +0000

    libtracker-db: Improve the journal API
    
    Added return values in some cases, and make it clearer that there is
    an API to iterate the journal and an API to write to it.
    
    Don't use global namespace for #defines for local use
    
    Move local functions above public functions
    
    libtracker-db: Improve db journal reader GErrors
    
    Use an enum not hardcoded values for journal data formats

 src/libtracker-db/tracker-db-journal.c |  666 +++++++++++++++++++++-----------
 src/libtracker-db/tracker-db-journal.h |   52 ++-
 src/libtracker-db/tracker-db-manager.c |    4 +-
 3 files changed, 478 insertions(+), 244 deletions(-)
---
diff --git a/src/libtracker-db/tracker-db-journal.c b/src/libtracker-db/tracker-db-journal.c
index b0510b6..30d5f5c 100644
--- a/src/libtracker-db/tracker-db-journal.c
+++ b/src/libtracker-db/tracker-db-journal.c
@@ -29,12 +29,33 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <errno.h>
+
+#include <glib/gstdio.h>
 
 #include <libtracker-common/tracker-crc32.h>
 
 #include "tracker-db-journal.h"
 
+#define JOURNAL_FILENAME  "tracker-store.journal"
+#define MIN_BLOCK_SIZE    1024
+
+/*
+ * data_format:
+ * #... 0000 0000 (total size is 4 bytes)
+ *            ||`- resource insert (all other bits must be 0 if 1)
+ *            |`-- object type (1 = id, 0 = cstring)
+ *            `--- operation type (0 = insert, 1 = delete)
+ */
+
+typedef enum {
+	DATA_FORMAT_RESOURCE_INSERT  = 1 << 0,
+	DATA_FORMAT_OBJECT_ID        = 1 << 1,
+	DATA_FORMAT_OPERATION_DELETE = 1 << 2
+} DataFormat;
+
 static struct {
+	gchar *filename;
 	GMappedFile *file;
 	const gchar *current;
 	const gchar *end;
@@ -47,12 +68,12 @@ static struct {
 	guint32 p_id;
 	guint32 o_id;
 	const gchar *object;
-} journal_reader;
+} reader;
 
 static struct {
-	gchar *filename;
+	gchar *journal_filename;
 	FILE *journal;
-	gsize current_size;
+	gsize cur_size;
 	guint cur_block_len;
 	guint cur_block_alloc;
 	gchar *cur_block;
@@ -60,86 +81,108 @@ static struct {
 	guint cur_pos;
 } writer;
 
-#define TRACKER_DB_JOURNAL_LOG_FILENAME  "tracker-store.journal"
-#define MIN_BLOCK_SIZE                   1024
+static guint32
+read_uint32 (const gchar *data)
+{
+	return data[0] << 24 |
+	       data[1] << 16 |
+	       data[2] << 8 |
+	       data[3];
+}
 
-gsize
-tracker_db_journal_get_size (void)
+static gint
+nearest_pow (gint num)
 {
-	return current_size;
+	gint n = 1;
+	while (n < num)
+		n <<= 1;
+	return n;
 }
 
-const gchar *
-tracker_db_journal_filename (void)
+static void
+cur_block_maybe_expand (guint len)
 {
-	if (!writer.filename) {
-		writer.filename = g_build_filename (g_get_user_data_dir (),
-		                                    "tracker",
-		                                    "data",
-		                                    TRACKER_DB_JOURNAL_LOG_FILENAME,
-		                                    NULL);
-	}
+	guint want_alloc = writer.cur_block_len + len;
 
-	return (const gchar *) filename;
+	if (want_alloc > writer.cur_block_alloc) {
+		want_alloc = nearest_pow (want_alloc);
+		want_alloc = MAX (want_alloc, MIN_BLOCK_SIZE);
+		writer.cur_block = g_realloc (writer.cur_block, want_alloc);
+		writer.cur_block_alloc = want_alloc;
+	}
 }
 
 static void
-kill_cur_block (void)
+cur_block_kill (void)
 {
 	writer.cur_block_len = 0;
 	writer.cur_pos = 0;
 	writer.cur_entry_amount = 0;
 	writer.cur_block_alloc = 0;
+
 	g_free (writer.cur_block);
 	writer.cur_block = NULL;
 }
 
-static gint
-nearest_pow (gint num)
+static void
+cur_setnum (gchar   *dest,
+            guint   *pos,
+            guint32  val)
 {
-	gint n = 1;
-	while (n < num)
-		n <<= 1;
-	return n;
+	memset (dest + (*pos)++, val >> 24 & 0xff, 1);
+	memset (dest + (*pos)++, val >> 16 & 0xff, 1);
+	memset (dest + (*pos)++, val >>  8 & 0xff, 1);
+	memset (dest + (*pos)++, val >>  0 & 0xff, 1);
 }
 
 static void
-cur_block_maybe_expand (guint len)
+cur_setstr (gchar       *dest,
+            guint       *pos,
+            const gchar *str,
+            gsize        len)
 {
-	guint want_alloc = writer.cur_block_len + len;
+	memcpy (dest + *pos, str, len);
+	(*pos) += len;
+	memset (dest + (*pos)++, 0 & 0xff, 1);
+}
 
-	if (want_alloc > writer.cur_block_alloc) {
-		want_alloc = nearest_pow (want_alloc);
-		want_alloc = MAX (want_alloc, MIN_BLOCK_SIZE);
-		writer.cur_block = g_realloc (writer.cur_block, want_alloc);
-		writer.cur_block_alloc = want_alloc;
-	}
+GQuark
+tracker_db_journal_error_quark (void)
+{
+	return g_quark_from_static_string (TRACKER_DB_JOURNAL_ERROR_DOMAIN);
 }
 
-void
-tracker_db_journal_open (const gchar *filen)
+gboolean
+tracker_db_journal_init (const gchar *filename)
 {
 	struct stat st;
 
+	g_return_val_if_fail (writer.journal == NULL, FALSE);
+
 	writer.cur_block_len = 0;
 	writer.cur_pos = 0;
 	writer.cur_entry_amount = 0;
 	writer.cur_block_alloc = 0;
 	writer.cur_block = NULL;
 
-	if (!filen) {
-		tracker_db_journal_filename ();
+	/* Used mostly for testing */
+	if (G_UNLIKELY (filename)) {
+		writer.journal_filename = g_strdup (filename);
 	} else {
-		writer.filename = g_strdup (filen);
+		writer.journal_filename = g_build_filename (g_get_user_data_dir (),
+		                                            "tracker",
+		                                            "data",
+		                                            JOURNAL_FILENAME,
+		                                            NULL);
 	}
 
-	writer.journal = fopen (writer.filename, "a");
+	writer.journal = g_fopen (writer.journal_filename, "a");
 
-	if (stat (writer.filename, &st) == 0) {
-		writer.current_size = (gsize) st.st_size;
+	if (g_stat (writer.journal_filename, &st) == 0) {
+		writer.cur_size = (gsize) st.st_size;
 	}
 
-	if (writer.current_size == 0) {
+	if (writer.cur_size == 0) {
 		g_assert (writer.cur_block_len == 0);
 		g_assert (writer.cur_block_alloc == 0);
 		g_assert (writer.cur_block == NULL);
@@ -158,163 +201,226 @@ tracker_db_journal_open (const gchar *filen)
 
 		write (fileno (writer.journal), writer.cur_block, 8);
 
-		writer.current_size += 8;
+		writer.cur_size += 8;
+
+		cur_block_kill ();
+	}
+
+	return TRUE;
+}
 
-		kill_cur_block ();
+gboolean
+tracker_db_journal_shutdown (void)
+{
+	if (journal == NULL) {
+		return TRUE;
 	}
+
+	fclose (journal);
+	journal = NULL;
+
+	g_free (journal_filename);
+	journal_filename = NULL;
+
+	return TRUE;
 }
 
-void
+gsize
+tracker_db_journal_get_size (void)
+{
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	return cur_size;
+}
+
+const gchar *
+tracker_db_journal_get_filename (void)
+{
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	return (const gchar*) journal_filename;
+}
+
+gboolean
 tracker_db_journal_start_transaction (void)
 {
-	guint size = sizeof (guint32) * 3;
+	guint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
 
+	size = sizeof (guint32) * 3;
 	cur_block_maybe_expand (size);
 
-	/* Leave space for size, amount and crc 
-	 * Check and keep in sync the offset variable at 
+	/* Leave space for size, amount and crc
+	 * Check and keep in sync the offset variable at
 	 * tracker_db_journal_commit_transaction too */
 
 	memset (writer.cur_block, 0, size);
 
 	writer.cur_pos = writer.cur_block_len = size;
 	writer.cur_entry_amount = 0;
-}
-
-static void
-cur_setnum (gchar   *dest,
-            guint   *pos,
-            guint32  val)
-{
-	memset (dest + (*pos)++, val >> 24 & 0xff, 1);
-	memset (dest + (*pos)++, val >> 16 & 0xff, 1);
-	memset (dest + (*pos)++, val >>  8 & 0xff, 1);
-	memset (dest + (*pos)++, val >>  0 & 0xff, 1);
-}
 
-static void
-cur_setstr (gchar       *dest,
-            guint       *pos,
-            const gchar *str,
-            gsize        len)
-{
-	memcpy (dest + *pos, str, len);
-	(*pos) += len;
-	memset (dest + (*pos)++, 0 & 0xff, 1);
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_delete_statement (guint32      s_id,
                                             guint32      p_id,
                                             const gchar *object)
 {
-	gint o_len = strlen (object);
-	gchar data_format = 0x04;
-	gint size = (sizeof (guint32) * 3) + o_len + 1;
+	gint o_len;
+	DataFormat df;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	o_len = strlen (object);
+	df = DATA_FORMAT_OPERATION_DELETE;
+
+	size = (sizeof (guint32) * 3) + o_len + 1;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (writer.cur_block, &writer.cur_pos, data_format);
+	cur_setnum (writer.cur_block, &writer.cur_pos, df);
 	cur_setnum (writer.cur_block, &writer.cur_pos, s_id);
 	cur_setnum (writer.cur_block, &writer.cur_pos, p_id);
 	cur_setstr (writer.cur_block, &writer.cur_pos, object, o_len);
 
 	writer.cur_entry_amount++;
 	writer.cur_block_len += size;
-}
 
+	return TRUE;
+}
 
-void
+gboolean
 tracker_db_journal_append_delete_statement_id (guint32 s_id,
                                                guint32 p_id,
                                                guint32 o_id)
 {
-	gchar data_format = 0x06;
-	gint size = sizeof (guint32) * 4;
+	DataFormat df;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	df = DATA_FORMAT_OPERATION_DELETE | DATA_FORMAT_OBJECT_ID;
+	size = sizeof (guint32) * 4;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (writer.cur_block, &writer.cur_pos, data_format);
+	cur_setnum (writer.cur_block, &writer.cur_pos, df);
 	cur_setnum (writer.cur_block, &writer.cur_pos, s_id);
 	cur_setnum (writer.cur_block, &writer.cur_pos, p_id);
 	cur_setnum (writer.cur_block, &writer.cur_pos, o_id);
 
 	writer.cur_entry_amount++;
 	writer.cur_block_len += size;
+
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_insert_statement (guint32      s_id,
                                             guint32      p_id,
                                             const gchar *object)
 {
-	gint o_len = strlen (object);
-	gchar data_format = 0x00;
-	gint size = (sizeof (guint32) * 3) + o_len + 1;
+	gint o_len;
+	DataFormat df;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	o_len = strlen (object);
+	df = 0x00;
+	size = (sizeof (guint32) * 3) + o_len + 1;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (writer.cur_block, &writer.cur_pos, data_format);
+	cur_setnum (writer.cur_block, &writer.cur_pos, df);
 	cur_setnum (writer.cur_block, &writer.cur_pos, s_id);
 	cur_setnum (writer.cur_block, &writer.cur_pos, p_id);
 	cur_setstr (writer.cur_block, &writer.cur_pos, object, o_len);
 
 	writer.cur_entry_amount++;
 	writer.cur_block_len += size;
+
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_insert_statement_id (guint32 s_id,
                                                guint32 p_id,
                                                guint32 o_id)
 {
-	gchar data_format = 0x02;
-	gint size = sizeof (guint32) * 4;
+	DataFormat df;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	df = DATA_FORMAT_OBJECT_ID;
+	size = sizeof (guint32) * 4;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (writer.cur_block, &writer.cur_pos, data_format);
+	cur_setnum (writer.cur_block, &writer.cur_pos, df);
 	cur_setnum (writer.cur_block, &writer.cur_pos, s_id);
 	cur_setnum (writer.cur_block, &writer.cur_pos, p_id);
 	cur_setnum (writer.cur_block, &writer.cur_pos, o_id);
 
 	writer.cur_entry_amount++;
 	writer.cur_block_len += size;
+
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_resource (guint32      s_id,
                                     const gchar *uri)
 {
-	gint o_len = strlen (uri);
-	gchar data_format = 0x01;
-	gint size = (sizeof (guint32) * 2) + o_len + 1;
+	gint o_len;
+	DataFormat df;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	o_len = strlen (uri);
+	df = DATA_FORMAT_RESOURCE_INSERT;
+	size = (sizeof (guint32) * 2) + o_len + 1;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (writer.cur_block, &writer.cur_pos, data_format);
+	cur_setnum (writer.cur_block, &writer.cur_pos, df);
 	cur_setnum (writer.cur_block, &writer.cur_pos, s_id);
 	cur_setstr (writer.cur_block, &writer.cur_pos, uri, o_len);
 
 	writer.cur_entry_amount++;
 	writer.cur_block_len += size;
+
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_rollback_transaction (void)
 {
-	kill_cur_block ();
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	cur_block_kill ();
+
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_commit_transaction (void)
 {
 	guint32 crc;
-	guint begin_pos = 0;
-	guint size = sizeof (guint32);
-	guint offset = sizeof(guint32) * 3;
+	guint begin_pos;
+	guint size;
+	guint offset;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
 
-	g_assert (writer.journal);
+	begin_pos = 0;
+	size = sizeof (guint32);
+	offset = sizeof (guint32) * 3;
 
 	cur_block_maybe_expand (size);
 
@@ -330,253 +436,367 @@ tracker_db_journal_commit_transaction (void)
 	crc = tracker_crc32 (writer.cur_block + offset, writer.cur_block_len - offset);
 	cur_setnum (writer.cur_block, &begin_pos, crc);
 
-	write (fileno (writer.journal), writer.cur_block, writer.cur_block_len);
+	/* FIXME: What if we don't write all of len, needs improving. */
+	if (write (fileno (writer.journal), writer.cur_block, writer.cur_block_len) == -1) {
+		g_critical ("Could not write to journal, %s", g_strerror (errno));
+		return FALSE;
+	}
 
-	writer.current_size += writer.cur_block_len;
+	writer.cur_size += writer.cur_block_len;
+	cur_block_kill ();
 
-	kill_cur_block ();
+	return TRUE;
 }
 
-void 
+gboolean
 tracker_db_journal_fsync (void)
 {
-	g_assert (writer.journal);
+	g_return_val_if_fail (writer.journal != NULL, FALSE);
 
-	fsync (fileno (writer.journal));
+	return fsync (fileno (writer.journal)) == 0;
 }
 
-void
-tracker_db_journal_close (void)
+/*
+ * Reader API
+ */
+gboolean
+tracker_db_journal_reader_init (const gchar *filename)
 {
-	g_assert (writer.journal);
-
-	fclose (writer.journal);
-	writer.journal = NULL;
+	GError *error = NULL;
+	gchar *filename_used;
 
-	g_free (writer.filename);
-	writer.filename = NULL;
-}
+	g_return_val_if_fail (reader.file == NULL, FALSE);
 
-void
-tracker_db_journal_reader_init (const gchar *filen)
-{
-	if (!filen) {
-		tracker_db_journal_filename ();
+	/* Used mostly for testing */
+	if (G_UNLIKELY (filename)) {
+		filename_used = g_strdup (filename);
 	} else {
-		filename = g_strdup (filen);
+		filename_used = g_build_filename (g_get_user_data_dir (),
+		                                  "tracker",
+		                                  "data",
+		                                  JOURNAL_FILENAME,
+		                                  NULL);
+	}
+
+	reader.type = TRACKER_DB_JOURNAL_START;
+	reader.filename = filename_used;
+	reader.file = g_mapped_file_new (reader.filename, FALSE, &error);
+
+	if (error) {
+		g_warning ("Could not create TrackerDBJournalEntry for file '%s', %s", 
+		           reader.filename,
+		           error->message ? error->message : "no error given");
+		g_error_free (error);
+		tracker_db_journal_reader_shutdown ();
+
+		return FALSE;
 	}
 
-	/* TODO error handling */
-	journal_reader.file = g_mapped_file_new (filename, FALSE, NULL);
-	journal_reader.current = g_mapped_file_get_contents (journal_reader.file);
-	journal_reader.end = journal_reader.current + g_mapped_file_get_length (journal_reader.file);
+	reader.current = g_mapped_file_get_contents (reader.file);
+	reader.end = reader.current + g_mapped_file_get_length (reader.file);
 
 	/* verify journal file header */
-	g_assert (journal_reader.end - journal_reader.current >= 8);
-	g_assert (memcmp (journal_reader.current, "trlog\001", 8) == 0);
-	journal_reader.current += 8;
+	g_assert (reader.end - reader.current >= 8);
+
+	g_assert_cmpint (reader.current[0], ==, 't');
+	g_assert_cmpint (reader.current[1], ==, 'r');
+	g_assert_cmpint (reader.current[2], ==, 'l');
+	g_assert_cmpint (reader.current[3], ==, 'o');
+	g_assert_cmpint (reader.current[4], ==, 'g');
+	g_assert_cmpint (reader.current[5], ==, '\0');
+	g_assert_cmpint (reader.current[6], ==, '0');
+	g_assert_cmpint (reader.current[7], ==, '1');
+
+	reader.current += 8;
+
+	return TRUE;
 }
 
-static guint32 read_uint32 (const gchar *data)
+gboolean
+tracker_db_journal_reader_shutdown (void)
 {
-	return data[0] << 24 |
-	       data[1] << 16 |
-	       data[2] << 8 |
-	       data[3];
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+
+#if GLIB_CHECK_VERSION(2,22,0)
+	g_mapped_file_unref (reader.file);
+#else
+	g_mapped_file_free (reader.file);
+#endif
+
+	reader.file = NULL;
+
+	g_free (reader.filename);
+	reader.filename = NULL;
+
+	reader.current = NULL;
+	reader.end = NULL;
+	reader.entry_begin = NULL;
+	reader.entry_end = NULL;
+	reader.amount_of_triples = 0;
+	reader.type = TRACKER_DB_JOURNAL_START;
+	reader.uri = NULL;
+	reader.s_id = 0;
+	reader.p_id = 0;
+	reader.o_id = 0;
+	reader.object = NULL;
+
+	return TRUE;
+}
+
+TrackerDBJournalEntryType
+tracker_db_journal_reader_get_type (void)
+{
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+
+	return reader.type;
 }
 
 gboolean
-tracker_db_journal_next (void)
+tracker_db_journal_reader_next (GError **error)
 {
-	if (journal_reader.type == TRACKER_DB_JOURNAL_START ||
-	    journal_reader.type == TRACKER_DB_JOURNAL_END_TRANSACTION) {
-		/* expect new transaction or end of file */
+	g_return_val_if_fail (reader.file != NULL, FALSE);
 
+	if (reader.type == TRACKER_DB_JOURNAL_START ||
+	    reader.type == TRACKER_DB_JOURNAL_END_TRANSACTION) {
+		/* expect new transaction or end of file */
 		guint32 entry_size;
 		guint32 crc32;
+		guint32 read_size;
 
-		if (journal_reader.current >= journal_reader.end) {
-			/* end of journal reached */
+		if (reader.current >= reader.end) {
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "End of journal reached");
 			return FALSE;
 		}
 
-		if (journal_reader.end - journal_reader.current < sizeof (guint32)) {
-			/* damaged journal entry */
+		if (reader.end - reader.current < sizeof (guint32)) {
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "Damaged journal entry, < sizeof(guint32) at start/end of journal");
 			return FALSE;
 		}
 
-		journal_reader.entry_begin = journal_reader.current;
-		entry_size = read_uint32 (journal_reader.current);
-		journal_reader.entry_end = journal_reader.entry_begin + entry_size;
-		if (journal_reader.end < journal_reader.entry_end) {
-			/* damaged journal entry */
+		reader.entry_begin = reader.current;
+		entry_size = read_uint32 (reader.current);
+		reader.entry_end = reader.entry_begin + entry_size;
+
+		if (reader.end < reader.entry_end) {
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "Damaged journal entry, end < entry end");
 			return FALSE;
 		}
-		journal_reader.current += 4;
+
+		reader.current += 4;
 
 		/* compare with entry_size at end */
-		if (entry_size != read_uint32 (journal_reader.entry_end - 4)) {
+		read_size = read_uint32 (reader.entry_end - 4);
+
+		if (entry_size != read_size) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "Damaged journal entry, %d != %d (size != size read)", 
+			             entry_size, 
+			             read_size);
 			return FALSE;
 		}
 
-		journal_reader.amount_of_triples = read_uint32 (journal_reader.current);
-		journal_reader.current += 4;
+		reader.amount_of_triples = read_uint32 (reader.current);
+		reader.current += 4;
 
-		crc32 = read_uint32 (journal_reader.current);
-		journal_reader.current += 4;
+		crc32 = read_uint32 (reader.current);
+		reader.current += 4;
 
 		/* verify checksum */
-		if (crc32 != tracker_crc32 (journal_reader.entry_begin, entry_size)) {
+		if (crc32 != tracker_crc32 (reader.entry_begin, entry_size)) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "Damaged journal entry, crc32 failed");
 			return FALSE;
 		}
 
-		journal_reader.type = TRACKER_DB_JOURNAL_START_TRANSACTION;
+		reader.type = TRACKER_DB_JOURNAL_START_TRANSACTION;
 		return TRUE;
-	} else if (journal_reader.amount_of_triples == 0) {
+	} else if (reader.amount_of_triples == 0) {
 		/* end of transaction */
 
-		if (journal_reader.current + 4 != journal_reader.entry_end) {
+		if (reader.current + 4 != reader.entry_end) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "Damaged journal entry, %p != %p (end of transaction with 0 triples)",
+			             reader.current + 4,
+			             reader.entry_end);
 			return FALSE;
 		}
 
-		journal_reader.type = TRACKER_DB_JOURNAL_END_TRANSACTION;
+		reader.type = TRACKER_DB_JOURNAL_END_TRANSACTION;
 		return TRUE;
 	} else {
-		guint32 data_format;
+		DataFormat df;
 		gsize str_length;
 
-		if (journal_reader.end - journal_reader.current < sizeof (guint32)) {
+		if (reader.end - reader.current < sizeof (guint32)) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+			             "Damaged journal entry, %d < sizeof(guint32)",
+			             (gint) (reader.end - reader.current));
 			return FALSE;
 		}
 
-		data_format = read_uint32 (journal_reader.current);
-		journal_reader.current += 4;
+		df = read_uint32 (reader.current);
+		reader.current += 4;
 
-		if (data_format == 1) {
-			journal_reader.type = TRACKER_DB_JOURNAL_RESOURCE;
+		if (df == DATA_FORMAT_RESOURCE_INSERT) {
+			reader.type = TRACKER_DB_JOURNAL_RESOURCE;
 
-			if (journal_reader.end - journal_reader.current < sizeof (guint32) + 1) {
+			if (reader.end - reader.current < sizeof (guint32) + 1) {
 				/* damaged journal entry */
+				g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+				             "Damaged journal entry, %d < sizeof(guint32) + 1 for resource",
+				             (gint) (reader.end - reader.current));
 				return FALSE;
 			}
 
-			journal_reader.s_id = read_uint32 (journal_reader.current);
-			journal_reader.current += 4;
+			reader.s_id = read_uint32 (reader.current);
+			reader.current += 4;
 
-			str_length = strnlen (journal_reader.current, journal_reader.end - journal_reader.current);
-			if (str_length == journal_reader.end - journal_reader.current) {
+			str_length = strnlen (reader.current, reader.end - reader.current);
+			if (str_length == reader.end - reader.current) {
 				/* damaged journal entry (no terminating '\0' character) */
+				g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+				             "Damaged journal entry, no terminating zero found for resource");
 				return FALSE;
+
 			}
-			if (!g_utf8_validate (journal_reader.current, -1, NULL)) {
+
+			if (!g_utf8_validate (reader.current, -1, NULL)) {
 				/* damaged journal entry (invalid UTF-8) */
+				g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+				             "Damaged journal entry, invalid UTF-8 for resource");
 				return FALSE;
 			}
-			journal_reader.uri = journal_reader.current;
-			journal_reader.current += str_length + 1;
+
+			reader.uri = reader.current;
+			reader.current += str_length + 1;
 		} else {
-			if (data_format & 4) {
-				if (data_format & 2) {
-					journal_reader.type = TRACKER_DB_JOURNAL_DELETE_STATEMENT_ID;
+			if (df & DATA_FORMAT_OPERATION_DELETE) {
+				if (df & DATA_FORMAT_OBJECT_ID) {
+					reader.type = TRACKER_DB_JOURNAL_DELETE_STATEMENT_ID;
 				} else {
-					journal_reader.type = TRACKER_DB_JOURNAL_DELETE_STATEMENT;
+					reader.type = TRACKER_DB_JOURNAL_DELETE_STATEMENT;
 				}
 			} else {
-				if (data_format & 2) {
-					journal_reader.type = TRACKER_DB_JOURNAL_INSERT_STATEMENT_ID;
+				if (df & DATA_FORMAT_OBJECT_ID) {
+					reader.type = TRACKER_DB_JOURNAL_INSERT_STATEMENT_ID;
 				} else {
-					journal_reader.type = TRACKER_DB_JOURNAL_INSERT_STATEMENT;
+					reader.type = TRACKER_DB_JOURNAL_INSERT_STATEMENT;
 				}
 			}
 
-			if (journal_reader.end - journal_reader.current < 2 * sizeof (guint32)) {
+			if (reader.end - reader.current < 2 * sizeof (guint32)) {
 				/* damaged journal entry */
+				g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+				             "Damaged journal entry, %d < 2 * sizeof(guint32)",
+				             (gint) (reader.end - reader.current));
 				return FALSE;
 			}
 
-			journal_reader.s_id = read_uint32 (journal_reader.current);
-			journal_reader.current += 4;
+			reader.s_id = read_uint32 (reader.current);
+			reader.current += 4;
 
-			journal_reader.p_id = read_uint32 (journal_reader.current);
-			journal_reader.current += 4;
+			reader.p_id = read_uint32 (reader.current);
+			reader.current += 4;
 
-			if (data_format & 2) {
-				if (journal_reader.end - journal_reader.current < sizeof (guint32)) {
+			if (df & DATA_FORMAT_OBJECT_ID) {
+				if (reader.end - reader.current < sizeof (guint32)) {
 					/* damaged journal entry */
+					g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+					             "Damaged journal entry, %d < sizeof(guint32) for data format 2",
+					             (gint) (reader.end - reader.current));
 					return FALSE;
 				}
 
-				journal_reader.o_id = read_uint32 (journal_reader.current);
-				journal_reader.current += 4;
+				reader.o_id = read_uint32 (reader.current);
+				reader.current += 4;
 			} else {
-				if (journal_reader.end - journal_reader.current < 1) {
+				if (reader.end - reader.current < 1) {
 					/* damaged journal entry */
+					g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+					             "Damaged journal entry, %d < 1",
+					             (gint) (reader.end - reader.current));
 					return FALSE;
 				}
 
-				str_length = strnlen (journal_reader.current, journal_reader.end - journal_reader.current);
-				if (str_length == journal_reader.end - journal_reader.current) {
+				str_length = strnlen (reader.current, reader.end - reader.current);
+				if (str_length == reader.end - reader.current) {
 					/* damaged journal entry (no terminating '\0' character) */
+					g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+					             "Damaged journal entry, no terminating zero found");
 					return FALSE;
 				}
-				if (!g_utf8_validate (journal_reader.current, -1, NULL)) {
+
+				if (!g_utf8_validate (reader.current, -1, NULL)) {
 					/* damaged journal entry (invalid UTF-8) */
+					g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, 
+					             "Damaged journal entry, invalid UTF-8");
 					return FALSE;
 				}
-				journal_reader.object = journal_reader.current;
-				journal_reader.current += str_length + 1;
+
+				reader.object = reader.current;
+				reader.current += str_length + 1;
 			}
 		}
 
-		journal_reader.amount_of_triples--;
+		reader.amount_of_triples--;
 		return TRUE;
 	}
 
+	g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Unknown reason");
+
 	return FALSE;
 }
 
-TrackerDBJournalEntryType
-tracker_db_journal_get_type (void)
+gboolean
+tracker_db_journal_reader_get_resource (guint32      *id,
+                                        const gchar **uri)
 {
-	return journal_reader.type;
-}
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+	g_return_val_if_fail (reader.type == TRACKER_DB_JOURNAL_RESOURCE, FALSE);
 
-void
-tracker_db_journal_get_resource (guint32      *id,
-                                 const gchar **uri)
-{
-	g_return_if_fail (journal_reader.type == TRACKER_DB_JOURNAL_RESOURCE);
+	*id = reader.s_id;
+	*uri = reader.uri;
 
-	*id = journal_reader.s_id;
-	*uri = journal_reader.uri;
+	return TRUE;
 }
 
-void
-tracker_db_journal_get_statement (guint32      *s_id,
-                                  guint32      *p_id,
-                                  const gchar **object)
+gboolean
+tracker_db_journal_reader_get_statement (guint32      *s_id,
+                                         guint32      *p_id,
+                                         const gchar **object)
 {
-	g_return_if_fail (journal_reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT ||
-	                  journal_reader.type == TRACKER_DB_JOURNAL_DELETE_STATEMENT);
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+	g_return_val_if_fail (reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT ||
+	                      reader.type == TRACKER_DB_JOURNAL_DELETE_STATEMENT,
+	                      FALSE);
+
+	*s_id = reader.s_id;
+	*p_id = reader.p_id;
+	*object = reader.object;
 
-	*s_id = journal_reader.s_id;
-	*p_id = journal_reader.p_id;
-	*object = journal_reader.object;
+	return TRUE;
 }
 
-void
-tracker_db_journal_get_statement_id (guint32    *s_id,
-                                     guint32    *p_id,
-                                     guint32    *o_id)
+gboolean
+tracker_db_journal_reader_get_statement_id (guint32 *s_id,
+                                            guint32 *p_id,
+                                            guint32 *o_id)
 {
-	g_return_if_fail (journal_reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT_ID ||
-	                  journal_reader.type == TRACKER_DB_JOURNAL_DELETE_STATEMENT_ID);
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+	g_return_val_if_fail (reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT_ID ||
+	                      reader.type == TRACKER_DB_JOURNAL_DELETE_STATEMENT_ID,
+	                      FALSE);
+
+	*s_id = reader.s_id;
+	*p_id = reader.p_id;
+	*o_id = reader.o_id;
 
-	*s_id = journal_reader.s_id;
-	*p_id = journal_reader.p_id;
-	*o_id = journal_reader.o_id;
+	return TRUE;
 }
diff --git a/src/libtracker-db/tracker-db-journal.h b/src/libtracker-db/tracker-db-journal.h
index 2ebff17..3034234 100644
--- a/src/libtracker-db/tracker-db-journal.h
+++ b/src/libtracker-db/tracker-db-journal.h
@@ -27,6 +27,9 @@
 
 G_BEGIN_DECLS
 
+#define TRACKER_DB_JOURNAL_ERROR_DOMAIN "TrackerDBJournal"
+#define TRACKER_DB_JOURNAL_ERROR        tracker_db_journal_error_quark()
+
 typedef enum {
 	TRACKER_DB_JOURNAL_START,
 	TRACKER_DB_JOURNAL_START_TRANSACTION,
@@ -38,42 +41,53 @@ typedef enum {
 	TRACKER_DB_JOURNAL_DELETE_STATEMENT_ID
 } TrackerDBJournalEntryType;
 
-const gchar* tracker_db_journal_filename                     (void);
-void         tracker_db_journal_open                         (const gchar *filen);
+GQuark       tracker_db_journal_error_quark                  (void);
+
+/*
+ * Writer API
+ */
+gboolean     tracker_db_journal_init                         (const gchar *filename);
+gboolean     tracker_db_journal_shutdown                     (void);
+
+const gchar* tracker_db_journal_get_filename                 (void);
+gsize        tracker_db_journal_get_size                     (void);
 
-void         tracker_db_journal_start_transaction            (void);
-void         tracker_db_journal_append_delete_statement      (guint32      s_id,
+gboolean     tracker_db_journal_start_transaction            (void);
+gboolean     tracker_db_journal_append_delete_statement      (guint32      s_id,
                                                               guint32      p_id,
                                                               const gchar *object);
-void         tracker_db_journal_append_delete_statement_id   (guint32      s_id,
+gboolean     tracker_db_journal_append_delete_statement_id   (guint32      s_id,
                                                               guint32      p_id,
                                                               guint32      o_id);
-void         tracker_db_journal_append_insert_statement      (guint32      s_id, 
+gboolean     tracker_db_journal_append_insert_statement      (guint32      s_id, 
                                                               guint32      p_id, 
                                                               const gchar *object);
-void         tracker_db_journal_append_insert_statement_id   (guint32      s_id,
+gboolean     tracker_db_journal_append_insert_statement_id   (guint32      s_id,
                                                               guint32      p_id,
                                                               guint32      o_id);
-void         tracker_db_journal_append_resource              (guint32      s_id,
+gboolean     tracker_db_journal_append_resource              (guint32      s_id,
                                                               const gchar *uri);
 
-void         tracker_db_journal_rollback_transaction         (void);
-void         tracker_db_journal_commit_transaction           (void);
+gboolean     tracker_db_journal_rollback_transaction         (void);
+gboolean     tracker_db_journal_commit_transaction           (void);
 
-void         tracker_db_journal_close                        (void);
-void         tracker_db_journal_fsync                        (void);
-gsize        tracker_db_journal_get_size                     (void);
+gboolean     tracker_db_journal_fsync                        (void);
 
-void         tracker_db_journal_reader_init                  (const gchar  *filen);
-gboolean     tracker_db_journal_next                         (void);
+/*
+ * Reader API
+ */
+gboolean     tracker_db_journal_reader_init                  (const gchar  *filename);
+gboolean     tracker_db_journal_reader_shutdown              (void);
 TrackerDBJournalEntryType
-             tracker_db_journal_get_type                     (void);
-void         tracker_db_journal_get_resource                 (guint32      *id,
+             tracker_db_journal_reader_get_type              (void);
+
+gboolean     tracker_db_journal_reader_next                  (GError      **error);
+gboolean     tracker_db_journal_reader_get_resource          (guint32      *id,
                                                               const gchar **uri);
-void         tracker_db_journal_get_statement                (guint32      *s_id,
+gboolean     tracker_db_journal_reader_get_statement         (guint32      *s_id,
                                                               guint32      *p_id,
                                                               const gchar **object);
-void         tracker_db_journal_get_statement_id             (guint32      *s_id,
+gboolean     tracker_db_journal_reader_get_statement_id      (guint32      *s_id,
                                                               guint32      *p_id,
                                                               guint32      *o_id);
 
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index 95f0955..72bceeb 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -865,8 +865,8 @@ db_manager_remove_all (gboolean rm_backup_and_log, gboolean not_meta)
 		GFile *file;
 		gchar *cpath;
 
-		cpath = g_strdup (tracker_db_journal_filename ());
-		tracker_db_journal_close ();
+		cpath = g_strdup (tracker_db_journal_get_filename ());
+		tracker_db_journal_shutdown ();
 		g_message ("  Removing journal:'%s'",
 		           cpath);
 		file = g_file_new_for_path (cpath);



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