[tracker/binary-log-2: 21/56] Added more feedback to journal API



commit 6d0478d3c4f4c690d1d4b30246fb82f9ea7c4e1a
Author: Martyn Russell <martyn lanedo com>
Date:   Mon Jan 4 18:08:02 2010 +0000

    Added more feedback to journal API
    
    - Now we return TRUE/FALSE to APIs
    - We have a GError for entry_next() API.
    - Test cases now work for journal writing (not reading yet).

 src/libtracker-data/tracker-data-manager.c |    2 +-
 src/libtracker-db/tracker-db-journal.c     |  414 ++++++++++++++++++---------
 src/libtracker-db/tracker-db-journal.h     |   33 ++-
 src/libtracker-db/tracker-db-manager.c     |    4 +-
 tests/libtracker-db/Makefile.am            |    2 +
 tests/libtracker-db/tracker-db-journal.c   |  172 ++++++++++---
 6 files changed, 439 insertions(+), 188 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 408b972..9eebb4c 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -829,7 +829,7 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 
 	iface = tracker_db_manager_get_db_interface ();
 
-	tracker_db_journal_init ();
+	tracker_db_journal_init (NULL);
 
 	if (is_first_time_index) {
 		TrackerClass **classes;
diff --git a/src/libtracker-db/tracker-db-journal.c b/src/libtracker-db/tracker-db-journal.c
index 48c2639..ac6d252 100644
--- a/src/libtracker-db/tracker-db-journal.c
+++ b/src/libtracker-db/tracker-db-journal.c
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include <glib/gstdio.h>
 
@@ -40,6 +41,7 @@
 #define MIN_BLOCK_SIZE    1024
 
 struct TrackerDBJournalEntry {
+	gchar *filename;
 	GMappedFile *file;
 	const gchar *current;
 	const gchar *end;
@@ -54,17 +56,21 @@ struct TrackerDBJournalEntry {
 	const gchar *object;
 };
 
-/*
- * Writer variables
- */
-static gchar *filename = NULL;
-static FILE *journal = NULL;
-static gsize cur_size = 0;
-static guint cur_block_len = 0;
-static guint cur_block_alloc = 0;
-static gchar *cur_block = NULL;
-static guint cur_entry_amount = 0;
-static guint cur_pos = 0;
+typedef struct TrackerDBJournal TrackerDBJournal;
+
+struct TrackerDBJournal {
+	gchar *filename;
+	FILE *file;
+
+	gsize cur_size;
+	guint cur_block_len;
+	guint cur_block_alloc;
+	gchar *cur_block;
+	guint cur_entry_amount;
+	guint cur_pos;
+};
+
+static TrackerDBJournal *journal = NULL;
 
 static guint32 
 read_uint32 (const gchar *data)
@@ -87,25 +93,26 @@ nearest_pow (gint num)
 static void
 cur_block_maybe_expand (guint len)
 {
-	guint want_alloc = cur_block_len + len;
+	guint want_alloc = journal->cur_block_len + len;
 
-	if (want_alloc > cur_block_alloc) {
+	if (want_alloc > journal->cur_block_alloc) {
 		want_alloc = nearest_pow (want_alloc);
 		want_alloc = MAX (want_alloc, MIN_BLOCK_SIZE);
-		cur_block = g_realloc (cur_block, want_alloc);
-		cur_block_alloc = want_alloc;
+		journal->cur_block = g_realloc (journal->cur_block, want_alloc);
+		journal->cur_block_alloc = want_alloc;
 	}
 }
 
 static void
 cur_block_kill (void)
 {
-	cur_block_len = 0;
-	cur_pos = 0;
-	cur_entry_amount = 0;
-	cur_block_alloc = 0;
-	g_free (cur_block);
-	cur_block = NULL;
+	journal->cur_block_len = 0;
+	journal->cur_pos = 0;
+	journal->cur_entry_amount = 0;
+	journal->cur_block_alloc = 0;
+
+	g_free (journal->cur_block);
+	journal->cur_block = NULL;
 }
 
 static void
@@ -130,38 +137,58 @@ cur_setstr (gchar       *dest,
 	memset (dest + (*pos)++, 0 & 0xff, 1);
 }
 
+GQuark
+tracker_db_journal_error_quark (void)
+{
+	return g_quark_from_static_string (TRACKER_DB_JOURNAL_ERROR_DOMAIN);
+}
+
 gboolean
-tracker_db_journal_init (void)
+tracker_db_journal_init (const gchar *filename)
 {
 	struct stat st;
 
-	filename = tracker_db_journal_filename ();
-	journal = g_fopen (filename, "a");
+	g_return_val_if_fail (journal == NULL, FALSE);
+
+	journal = g_new0 (TrackerDBJournal, 1);
 
-	if (g_stat (filename, &st) == 0) {
-		cur_size = (gsize) st.st_size;
+	/* Used mostly for testing */
+	if (G_UNLIKELY (filename)) {
+		journal->filename = g_strdup (filename);
+	} else {
+		journal->filename = g_build_filename (g_get_user_data_dir (),
+		                                      "tracker",
+		                                      "data",
+		                                      JOURNAL_FILENAME,
+		                                      NULL);
 	}
 
-	if (cur_size == 0) {
-		g_assert (cur_block_len == 0);
-		g_assert (cur_block_alloc == 0);
-		g_assert (cur_block == NULL);
-		g_assert (cur_block == NULL);
+	journal->file = g_fopen (journal->filename, "a");
+
+	if (g_stat (journal->filename, &st) == 0) {
+		journal->cur_size = (gsize) st.st_size;
+	}
+
+	if (journal->cur_size == 0) {
+		g_assert (journal->cur_block_len == 0);
+		g_assert (journal->cur_block_alloc == 0);
+		g_assert (journal->cur_block == NULL);
+		g_assert (journal->cur_block == NULL);
 
 		cur_block_maybe_expand (8);
 
-		cur_block[0] = 't';
-		cur_block[1] = 'r';
-		cur_block[2] = 'l';
-		cur_block[3] = 'o';
-		cur_block[4] = 'g';
-		cur_block[5] = '\0';
-		cur_block[6] = '0';
-		cur_block[7] = '1';
+		journal->cur_block[0] = 't';
+		journal->cur_block[1] = 'r';
+		journal->cur_block[2] = 'l';
+		journal->cur_block[3] = 'o';
+		journal->cur_block[4] = 'g';
+		journal->cur_block[5] = '\0';
+		journal->cur_block[6] = '0';
+		journal->cur_block[7] = '1';
 
-		write (fileno (journal), cur_block, 8);
+		write (fileno (journal->file), journal->cur_block, 8);
 
-		cur_size += 8;
+		journal->cur_size += 8;
 
 		cur_block_kill ();
 	}
@@ -172,13 +199,16 @@ tracker_db_journal_init (void)
 gboolean
 tracker_db_journal_shutdown (void)
 {
-	g_assert (journal);
+	g_return_val_if_fail (journal != NULL, FALSE);
 
-	fclose (journal);
-	journal = NULL;
+	if (journal->file) {
+		fclose (journal->file);
+	}
+
+	g_free (journal->filename);
 
-	g_free (filename);
-	filename = NULL;
+	g_free (journal);
+	journal = NULL;
 
 	return TRUE;
 }
@@ -186,203 +216,276 @@ tracker_db_journal_shutdown (void)
 gsize
 tracker_db_journal_get_size (void)
 {
-	return cur_size;
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	return journal->cur_size;
 }
 
 const gchar *
-tracker_db_journal_filename (void)
+tracker_db_journal_get_filename (void)
 {
-	if (!filename) {
-		filename = g_build_filename (g_get_user_data_dir (),
-		                             "tracker",
-		                             "data",
-		                             JOURNAL_FILENAME,
-		                             NULL);
-	}
+	g_return_val_if_fail (journal != NULL, FALSE);
 
-	return (const gchar*) filename;
+	return (const gchar*) journal->filename;
 }
 
-void
+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
 	 * tracker_db_journal_commit_transaction too */
 
-	memset (cur_block, 0, size);
+	memset (journal->cur_block, 0, size);
+
+	journal->cur_pos = journal->cur_block_len = size;
+	journal->cur_entry_amount = 0;
 
-	cur_pos = cur_block_len = size;
-	cur_entry_amount = 0;
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_delete_statement (guint32      s_code,
                                             guint32      p_code,
                                             const gchar *object)
 {
-	gint o_len = strlen (object);
-	gchar data_format = 0x04;
-	gint size = (sizeof (guint32) * 3) + o_len + 1;
+	gint o_len;
+	gchar data_format;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	o_len = strlen (object);
+	data_format = 0x04;
+	size = (sizeof (guint32) * 3) + o_len + 1;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (cur_block, &cur_pos, data_format);
-	cur_setnum (cur_block, &cur_pos, s_code);
-	cur_setnum (cur_block, &cur_pos, p_code);
-	cur_setstr (cur_block, &cur_pos, object, o_len);
+	cur_setnum (journal->cur_block, &journal->cur_pos, data_format);
+	cur_setnum (journal->cur_block, &journal->cur_pos, s_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, p_code);
+	cur_setstr (journal->cur_block, &journal->cur_pos, object, o_len);
+
+	journal->cur_entry_amount++;
+	journal->cur_block_len += size;
 
-	cur_entry_amount++;
-	cur_block_len += size;
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_delete_statement_code (guint32 s_code,
                                                  guint32 p_code,
                                                  guint32 o_code)
 {
-	gchar data_format = 0x06;
-	gint size = sizeof (guint32) * 4;
+	gchar data_format;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	data_format = 0x06;
+	size = sizeof (guint32) * 4;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (cur_block, &cur_pos, data_format);
-	cur_setnum (cur_block, &cur_pos, s_code);
-	cur_setnum (cur_block, &cur_pos, p_code);
-	cur_setnum (cur_block, &cur_pos, o_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, data_format);
+	cur_setnum (journal->cur_block, &journal->cur_pos, s_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, p_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, o_code);
+
+	journal->cur_entry_amount++;
+	journal->cur_block_len += size;
 
-	cur_entry_amount++;
-	cur_block_len += size;
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_insert_statement (guint32      s_code,
                                             guint32      p_code,
                                             const gchar *object)
 {
-	gint o_len = strlen (object);
-	gchar data_format = 0x00;
-	gint size = (sizeof (guint32) * 3) + o_len + 1;
+	gint o_len;
+	gchar data_format;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	o_len = strlen (object);
+	data_format = 0x00;
+	size = (sizeof (guint32) * 3) + o_len + 1;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (cur_block, &cur_pos, data_format);
-	cur_setnum (cur_block, &cur_pos, s_code);
-	cur_setnum (cur_block, &cur_pos, p_code);
-	cur_setstr (cur_block, &cur_pos, object, o_len);
+	cur_setnum (journal->cur_block, &journal->cur_pos, data_format);
+	cur_setnum (journal->cur_block, &journal->cur_pos, s_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, p_code);
+	cur_setstr (journal->cur_block, &journal->cur_pos, object, o_len);
+
+	journal->cur_entry_amount++;
+	journal->cur_block_len += size;
 
-	cur_entry_amount++;
-	cur_block_len += size;
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_insert_statement_code (guint32 s_code,
                                                  guint32 p_code,
                                                  guint32 o_code)
 {
-	gchar data_format = 0x02;
-	gint size = sizeof (guint32) * 4;
+	gchar data_format;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	data_format = 0x02;
+	size = sizeof (guint32) * 4;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (cur_block, &cur_pos, data_format);
-	cur_setnum (cur_block, &cur_pos, s_code);
-	cur_setnum (cur_block, &cur_pos, p_code);
-	cur_setnum (cur_block, &cur_pos, o_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, data_format);
+	cur_setnum (journal->cur_block, &journal->cur_pos, s_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, p_code);
+	cur_setnum (journal->cur_block, &journal->cur_pos, o_code);
+
+	journal->cur_entry_amount++;
+	journal->cur_block_len += size;
 
-	cur_entry_amount++;
-	cur_block_len += size;
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_append_resource (guint32      s_code,
                                     const gchar *uri)
 {
-	gint o_len = strlen (uri);
-	gchar data_format = 0x01;
-	gint size = (sizeof (guint32) * 2) + o_len + 1;
+	gint o_len;
+	gchar data_format;
+	gint size;
+
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	o_len = strlen (uri);
+	data_format = 0x01;
+	size = (sizeof (guint32) * 2) + o_len + 1;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (cur_block, &cur_pos, data_format);
-	cur_setnum (cur_block, &cur_pos, s_code);
-	cur_setstr (cur_block, &cur_pos, uri, o_len);
+	cur_setnum (journal->cur_block, &journal->cur_pos, data_format);
+	cur_setnum (journal->cur_block, &journal->cur_pos, s_code);
+	cur_setstr (journal->cur_block, &journal->cur_pos, uri, o_len);
+
+	journal->cur_entry_amount++;
+	journal->cur_block_len += size;
 
-	cur_entry_amount++;
-	cur_block_len += size;
+	return TRUE;
 }
 
-void
+gboolean
 tracker_db_journal_rollback_transaction (void)
 {
+	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 (journal);
+	begin_pos = 0;
+	size = sizeof (guint32);
+	offset = sizeof (guint32) * 3;
 
 	cur_block_maybe_expand (size);
 
-	cur_setnum (cur_block, &begin_pos, cur_block_len);
-	cur_setnum (cur_block, &begin_pos, cur_entry_amount);
+	cur_setnum (journal->cur_block, &begin_pos, journal->cur_block_len);
+	cur_setnum (journal->cur_block, &begin_pos, journal->cur_entry_amount);
 
-	cur_setnum (cur_block, &cur_pos, cur_block_len);
+	cur_setnum (journal->cur_block, &journal->cur_pos, journal->cur_block_len);
 
-	cur_block_len += size;
+	journal->cur_block_len += size;
 
 	/* CRC is calculated from entries until appended amount int */
 
-	crc = tracker_crc32 (cur_block + offset, cur_block_len - offset);
-	cur_setnum (cur_block, &begin_pos, crc);
+	crc = tracker_crc32 (journal->cur_block + offset, journal->cur_block_len - offset);
+	cur_setnum (journal->cur_block, &begin_pos, crc);
 
-	write (fileno (journal), cur_block, cur_block_len);
-
-	cur_size += cur_block_len;
+	/* FIXME: What if we don't write all of len, needs improving. */
+	if (write (fileno (journal->file), journal->cur_block, journal->cur_block_len) == -1) {
+		g_critical ("Could not write to journal, %s", g_strerror (errno));
+		return FALSE;
+	}
 
+	journal->cur_size += journal->cur_block_len;
 	cur_block_kill ();
+
+	return TRUE;
 }
 
-void 
+gboolean 
 tracker_db_journal_fsync (void)
 {
-	g_assert (journal);
+	g_return_val_if_fail (journal != NULL, FALSE);
 
-	fsync (fileno (journal));
+	return fsync (fileno (journal->file)) == 0;
 }
 
 /*
  * Reader API
  */
-
 TrackerDBJournalEntry *
-tracker_db_journal_entry_new (void)
+tracker_db_journal_entry_new (const gchar *filename)
 {
 	TrackerDBJournalEntry *entry;
-	const gchar *journal_filename;
+	GError *error = NULL;
+	gchar *journal_filename;
 
-	journal_filename = tracker_db_journal_filename ();
+	/* Used mostly for testing */
+	if (G_UNLIKELY (filename)) {
+		journal_filename = g_strdup (filename);
+	} else {
+		journal_filename = g_build_filename (g_get_user_data_dir (),
+		                                     "tracker",
+		                                     "data",
+		                                     JOURNAL_FILENAME,
+		                                     NULL);
+	}
 
 	entry = g_slice_new0 (TrackerDBJournalEntry);
 
-	/* TODO error handling */
-	entry->file = g_mapped_file_new (journal_filename, FALSE, NULL);
+	entry->type = TRACKER_DB_JOURNAL_START;
+	entry->filename = journal_filename;
+
+	entry->file = g_mapped_file_new (entry->filename, FALSE, &error);
+
+	if (error) {
+		g_warning ("Could not create TrackerDBJournalEntry for file '%s', %s", 
+		           entry->filename, 
+		           error->message ? error->message : "no error given");
+		g_error_free (error);
+		tracker_db_journal_entry_free (entry);
+
+		return NULL;
+	}
+
 	entry->current = g_mapped_file_get_contents (entry->file);
 	entry->end = entry->current + g_mapped_file_get_length (entry->file);
 
 	/* verify journal file header */
 	g_assert (entry->end - entry->current >= 8);
-	g_assert (memcmp (entry->current, "trlog\001", 8) == 0);
 	entry->current += 8;
 
 	return entry;
@@ -393,7 +496,17 @@ tracker_db_journal_entry_free (TrackerDBJournalEntry *entry)
 {
 	g_return_val_if_fail (entry != NULL, FALSE);
 
+	if (entry->file) {
+#if GLIB_CHECK_VERSION(2,22,0)
+		g_mapped_file_unref (entry->file);
+#else
+		g_mapped_file_free (entry->file);
+#endif
+	}
 
+	g_free (entry->filename);
+
+	g_slice_free (TrackerDBJournalEntry, entry);
 
 	return TRUE;
 }
@@ -407,7 +520,8 @@ tracker_db_journal_entry_get_type (TrackerDBJournalEntry *entry)
 }
 
 gboolean
-tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
+tracker_db_journal_entry_next (TrackerDBJournalEntry  *entry,
+                               GError                **error)
 {
 	g_return_val_if_fail (entry != NULL, FALSE);
 
@@ -416,29 +530,35 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 		/* expect new transaction or end of file */
 		guint32 entry_size;
 		guint32 crc32;
+		guint32 read_size;
 
 		if (entry->current >= entry->end) {
-			/* end of journal reached */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "End of journal reached");
 			return FALSE;
 		}
 
 		if (entry->end - entry->current < sizeof (guint32)) {
-			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, < sizeof(guint32) at start/end of journal");
 			return FALSE;
 		}
 
 		entry->entry_begin = entry->current;
 		entry_size = read_uint32 (entry->current);
 		entry->entry_end = entry->entry_begin + entry_size;
+
 		if (entry->end < entry->entry_end) {
-			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, end < entry end");
 			return FALSE;
 		}
+
 		entry->current += 4;
 
 		/* compare with entry_size at end */
-		if (entry_size != read_uint32 (entry->entry_end - 4)) {
+		read_size = read_uint32 (entry->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;
 		}
 
@@ -451,6 +571,7 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 		/* verify checksum */
 		if (crc32 != tracker_crc32 (entry->entry_begin, entry_size)) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, crc32 failed");
 			return FALSE;
 		}
 
@@ -461,6 +582,7 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 
 		if (entry->current + 4 != entry->entry_end) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, current + 4 != entry end");
 			return FALSE;
 		}
 
@@ -472,6 +594,7 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 
 		if (entry->end - entry->current < sizeof (guint32)) {
 			/* damaged journal entry */
+			g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, < sizeof(guint32)");
 			return FALSE;
 		}
 
@@ -483,6 +606,7 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 
 			if (entry->end - entry->current < sizeof (guint32) + 1) {
 				/* damaged journal entry */
+				g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, < sizeof(guint32) for RESOURCE");
 				return FALSE;
 			}
 
@@ -492,12 +616,17 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 			str_length = strnlen (entry->current, entry->end - entry->current);
 			if (str_length == entry->end - entry->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 (entry->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;
 			}
+
 			entry->uri = entry->current;
 			entry->current += str_length + 1;
 		} else {
@@ -517,6 +646,7 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 
 			if (entry->end - entry->current < 2 * sizeof (guint32)) {
 				/* damaged journal entry */
+				g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, < 2 * sizeof(guint32)");
 				return FALSE;
 			}
 
@@ -529,6 +659,7 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 			if (data_format & 2) {
 				if (entry->end - entry->current < sizeof (guint32)) {
 					/* damaged journal entry */
+					g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, < sizeof(guint32) for data format 2");
 					return FALSE;
 				}
 
@@ -537,18 +668,23 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 			} else {
 				if (entry->end - entry->current < 1) {
 					/* damaged journal entry */
+					g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Damaged journal entry, < 1");
 					return FALSE;
 				}
 
 				str_length = strnlen (entry->current, entry->end - entry->current);
 				if (str_length == entry->end - entry->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 (entry->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;
 				}
+
 				entry->object = entry->current;
 				entry->current += str_length + 1;
 			}
@@ -558,6 +694,8 @@ tracker_db_journal_entry_next (TrackerDBJournalEntry *entry)
 		return TRUE;
 	}
 
+	g_set_error (error, TRACKER_DB_JOURNAL_ERROR, 0, "Unknown reason");
+
 	return FALSE;
 }
 
diff --git a/src/libtracker-db/tracker-db-journal.h b/src/libtracker-db/tracker-db-journal.h
index 13bb1a6..4ba2a43 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 struct TrackerDBJournalEntry TrackerDBJournalEntry;
 
 typedef enum {
@@ -40,47 +43,49 @@ typedef enum {
 	TRACKER_DB_JOURNAL_DELETE_STATEMENT_CODE
 } TrackerDBJournalEntryType;
 
+GQuark       tracker_db_journal_error_quark                  (void);
+
 /*
  * Writer API
  */
-gboolean     tracker_db_journal_init                         (void);
+gboolean     tracker_db_journal_init                         (const gchar *filename);
 gboolean     tracker_db_journal_shutdown                     (void);
 
-const gchar* tracker_db_journal_filename                     (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_code,
+gboolean     tracker_db_journal_start_transaction            (void);
+gboolean     tracker_db_journal_append_delete_statement      (guint32      s_code,
                                                               guint32      p_code,
                                                               const gchar *object);
-void         tracker_db_journal_append_delete_statement_code (guint32      s_code,
+gboolean     tracker_db_journal_append_delete_statement_code (guint32      s_code,
                                                               guint32      p_code,
                                                               guint32      o_code);
-void         tracker_db_journal_append_insert_statement      (guint32      s_code, 
+gboolean     tracker_db_journal_append_insert_statement      (guint32      s_code, 
                                                               guint32      p_code, 
                                                               const gchar *object);
-void         tracker_db_journal_append_insert_statement_code (guint32      s_code,
+gboolean     tracker_db_journal_append_insert_statement_code (guint32      s_code,
                                                               guint32      p_code,
                                                               guint32      o_code);
-void         tracker_db_journal_append_resource              (guint32      s_code,
+gboolean     tracker_db_journal_append_resource              (guint32      s_code,
                                                               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);
+gboolean     tracker_db_journal_fsync                        (void);
 
 /*
  * Reader API
  */
 TrackerDBJournalEntry *
-             tracker_db_journal_entry_new                    (void);
+             tracker_db_journal_entry_new                    (const gchar            *filename);
 gboolean     tracker_db_journal_entry_free                   (TrackerDBJournalEntry  *entry);
 TrackerDBJournalEntryType
              tracker_db_journal_entry_get_type               (TrackerDBJournalEntry  *entry);
 
-gboolean     tracker_db_journal_entry_next                   (TrackerDBJournalEntry  *entry);
+gboolean     tracker_db_journal_entry_next                   (TrackerDBJournalEntry  *entry, 
+                                                              GError                **error);
 gboolean     tracker_db_journal_entry_get_resource           (TrackerDBJournalEntry  *entry,
                                                               guint32                *code,
                                                               const gchar           **uri);
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index a5eccea..8099a28 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;
 		const gchar *cpath;
 
-		cpath = tracker_db_journal_filename ();
-		g_message ("  Removing database:'%s'",
+		cpath = tracker_db_journal_get_filename ();
+		g_message ("  Removing journal:'%s'",
 		           cpath);
 		file = g_file_new_for_path (cpath);
 		g_file_delete (file, NULL, NULL);
diff --git a/tests/libtracker-db/Makefile.am b/tests/libtracker-db/Makefile.am
index 4a871d8..022453a 100644
--- a/tests/libtracker-db/Makefile.am
+++ b/tests/libtracker-db/Makefile.am
@@ -17,6 +17,8 @@ noinst_PROGRAMS = $(TEST_PROGS)
 #
 
 INCLUDES = 								\
+	-DTOP_SRCDIR=\"$(top_srcdir)\"					\
+	-DTOP_BUILDDIR=\"$(top_builddir)\"				\
 	-DG_LOG_DOMAIN=\"Tracker\"					\
 	-DTRACKER_COMPILATION						\
 	-I$(top_srcdir)/src						\
diff --git a/tests/libtracker-db/tracker-db-journal.c b/tests/libtracker-db/tracker-db-journal.c
index 1a47baf..1f8bc2d 100644
--- a/tests/libtracker-db/tracker-db-journal.c
+++ b/tests/libtracker-db/tracker-db-journal.c
@@ -17,44 +17,146 @@
  * Boston, MA  02110-1301, USA.
  */
 
+#include <glib/gstdio.h>
+
 #include <libtracker-common/tracker-crc32.h>
 
 #include <libtracker-db/tracker-db-journal.h>
 
 static void
-test_all (void)
+test_init_and_shutdown (void)
+{
+	gboolean result;
+
+	/* check double init/shutdown */
+	result = tracker_db_journal_init (NULL);
+	g_assert (result == TRUE);
+
+	result = tracker_db_journal_shutdown ();
+	g_assert (result == TRUE);
+
+	result = tracker_db_journal_init (NULL);
+	g_assert (result == TRUE);
+
+	result = tracker_db_journal_shutdown ();
+	g_assert (result == TRUE);
+}
+
+static void
+test_write_functions (void)
 {
-	tracker_db_journal_init ();
-
-	tracker_db_journal_start_transaction ();
-	tracker_db_journal_append_resource (10, "http://resource";);
-	tracker_db_journal_append_resource (11, "http://predicate";);
-	tracker_db_journal_append_delete_statement (10, 11, "test");
-	tracker_db_journal_commit_transaction ();
-
-	tracker_db_journal_start_transaction ();
-	tracker_db_journal_append_resource (12, "http://resource";);
-	tracker_db_journal_append_resource (13, "http://predicate";);
-	tracker_db_journal_append_resource (14, "http://resource";);
-	tracker_db_journal_append_delete_statement_code (12, 13, 14);
-	tracker_db_journal_commit_transaction ();
-
-
-	tracker_db_journal_start_transaction ();
-	tracker_db_journal_append_resource (15, "http://resource";);
-	tracker_db_journal_append_resource (16, "http://predicate";);
-	tracker_db_journal_append_insert_statement (15, 16, "test");
-	tracker_db_journal_commit_transaction ();
-
-	tracker_db_journal_start_transaction ();
-	tracker_db_journal_append_resource (17, "http://resource";);
-	tracker_db_journal_append_resource (18, "http://predicate";);
-	tracker_db_journal_append_resource (19, "http://resource";);
-	tracker_db_journal_append_insert_statement_code (17, 18, 19);
-	tracker_db_journal_commit_transaction ();
-
-	tracker_db_journal_fsync ();
+	gchar *path;
+	const gchar *filename;
+	gsize initial_size, actual_size;
+	gboolean result;
+
+	path = g_build_filename (TOP_SRCDIR, "tests", "libtracker-db", "tracker-store.journal", NULL);
+	g_unlink (path);
+
+	tracker_db_journal_init (path);
+
+        filename = tracker_db_journal_get_filename ();
+	g_assert (filename != NULL);
+	g_assert_cmpstr (filename, ==, path);
+
+	/* Size is 8 due to header */
+	actual_size = tracker_db_journal_get_size ();
+	g_assert_cmpint (actual_size, ==, 8);
+
+	/* Check with rollback, nothing is added */
+	initial_size = tracker_db_journal_get_size ();
+	result = tracker_db_journal_start_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (10, "http://resource";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (11, "http://predicate";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_delete_statement (10, 11, "test");
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_rollback_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+	actual_size = tracker_db_journal_get_size ();
+	g_assert_cmpint (initial_size, ==, actual_size);
+
+	/* Check with commit, somethign is added */
+	result = tracker_db_journal_start_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (12, "http://resource";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (13, "http://predicate";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (14, "http://resource";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_delete_statement_code (12, 13, 14);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_commit_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+	actual_size = tracker_db_journal_get_size ();
+	g_assert_cmpint (initial_size, !=, actual_size);
+
+	/* Test insert statement */
+	result = tracker_db_journal_start_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (15, "http://resource";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (16, "http://predicate";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_insert_statement (15, 16, "test");
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_commit_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+
+	/* Test insert code */
+	result = tracker_db_journal_start_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (17, "http://resource";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (18, "http://predicate";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_resource (19, "http://resource";);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_append_insert_statement_code (17, 18, 19);
+	g_assert_cmpint (result, ==, TRUE);
+	result = tracker_db_journal_commit_transaction ();
+	g_assert_cmpint (result, ==, TRUE);
+
+	/* Test fsync */
+	result = tracker_db_journal_fsync ();
+	g_assert_cmpint (result, ==, TRUE);
+
 	tracker_db_journal_shutdown ();
+
+	g_free (path);
+}
+
+static void
+test_read_functions (void)
+{
+	GError *error = NULL;
+	gchar *path;
+	gsize initial_size, actual_size;
+	gboolean result;
+	TrackerDBJournalEntry *entry;
+	TrackerDBJournalEntryType type;
+
+	path = g_build_filename (TOP_SRCDIR, "tests", "libtracker-db", "tracker-store.journal", NULL);
+
+	/* NOTE: we don't unlink here so we can use the data from the write tests */
+
+	/* Create an iterator */
+	entry = tracker_db_journal_entry_new (path);
+	g_assert (entry != NULL);
+
+	type = tracker_db_journal_entry_get_type (entry);
+	g_assert_cmpint (type, ==, TRACKER_DB_JOURNAL_START);
+
+	result = tracker_db_journal_entry_next (entry, &error);
+	g_assert_no_error (error);
+	g_assert_cmpint (result, ==, TRUE);
+
+	/* FIXME: unfinished */
+
+	g_free (path);
 }
 
 int
@@ -66,8 +168,12 @@ main (int argc, char **argv)
 	g_thread_init (NULL);
 	g_test_init (&argc, &argv, NULL);
 
-	g_test_add_func ("/libtracker-db/tracker-db-journal/open-append-commit-close",
-	                 test_all);
+	g_test_add_func ("/libtracker-db/tracker-db-journal/init-and-shutdown",
+	                 test_init_and_shutdown);
+	g_test_add_func ("/libtracker-db/tracker-db-journal/write-functions",
+	                 test_write_functions);
+	g_test_add_func ("/libtracker-db/tracker-db-journal/read-functions",
+	                 test_read_functions);
 
 	result = g_test_run ();
 



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