[tracker/binary-log-2: 14/47] Create TrackerDBJournalEntry for iterating through it



commit a5e06255df46f3eb708a53dc56aacf1a07fc88aa
Author: Martyn Russell <martyn lanedo com>
Date:   Mon Jan 4 15:37:06 2010 +0000

    Create TrackerDBJournalEntry for iterating through it
    
    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).
    
    Journal whitespace fixes
    
    libtracker-db: Fixed Philip's comments:
    
    - Revert writer variables to static vars (don't alloc)
    - Don't use g_slice for TrackerDBJournalEntry, use g_new instead.
    - the g_assert(memcpy()...) for the journal header was removed because
      it failed, this has been re-added using: g_assert_cmpint for each
      character and it works.
    
    libtracker-db: Improve db journal reader GErrors
    
    libtracker-db: Use global structure for journal reader and use s/entry/reader/ for API

 src/libtracker-data/tracker-data-manager.c |    2 +-
 src/libtracker-db/tracker-db-journal.c     |  507 +++++++++++++++++++---------
 src/libtracker-db/tracker-db-journal.h     |   42 ++-
 src/libtracker-db/tracker-db-manager.c     |    4 +-
 tests/libtracker-db/Makefile.am            |    2 +
 tests/libtracker-db/tracker-db-journal.c   |  174 ++++++++--
 6 files changed, 521 insertions(+), 210 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 7cead83..0810d16 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -830,7 +830,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 c7c666d..e4ff221 100644
--- a/src/libtracker-db/tracker-db-journal.c
+++ b/src/libtracker-db/tracker-db-journal.c
@@ -29,6 +29,9 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <errno.h>
+
+#include <glib/gstdio.h>
 
 #include <libtracker-common/tracker-crc32.h>
 
@@ -38,6 +41,7 @@
 #define MIN_BLOCK_SIZE    1024
 
 static struct {
+	gchar *filename;
 	GMappedFile *file;
 	const gchar *current;
 	const gchar *end;
@@ -50,18 +54,19 @@ static struct {
 	guint32 p_code;
 	guint32 o_code;
 	const gchar *object;
-} journal_reader;
+} reader;
 
-static gchar *filename = NULL;
+static gchar *journal_filename = NULL;
 static FILE *journal = NULL;
-static gsize current_size = 0;
+
+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;
 
-static guint32 
+static guint32
 read_uint32 (const gchar *data)
 {
 	return data[0] << 24 |
@@ -99,13 +104,14 @@ cur_block_kill (void)
 	cur_pos = 0;
 	cur_entry_amount = 0;
 	cur_block_alloc = 0;
+
 	g_free (cur_block);
 	cur_block = NULL;
 }
 
 static void
-cur_setnum (gchar   *dest, 
-            guint   *pos, 
+cur_setnum (gchar   *dest,
+            guint   *pos,
             guint32  val)
 {
 	memset (dest + (*pos)++, val >> 24 & 0xff, 1);
@@ -115,9 +121,9 @@ cur_setnum (gchar   *dest,
 }
 
 static void
-cur_setstr (gchar       *dest, 
-            guint       *pos, 
-            const gchar *str, 
+cur_setstr (gchar       *dest,
+            guint       *pos,
+            const gchar *str,
             gsize        len)
 {
 	memcpy (dest + *pos, str, len);
@@ -125,19 +131,37 @@ 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 = fopen (filename, "a");
+	g_return_val_if_fail (journal == NULL, FALSE);
 
-	if (stat (filename, &st) == 0) {
-		current_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 (current_size == 0) {
+	journal = g_fopen (journal_filename, "a");
+
+	if (g_stat (journal_filename, &st) == 0) {
+		cur_size = (gsize) st.st_size;
+	}
+
+	if (cur_size == 0) {
 		g_assert (cur_block_len == 0);
 		g_assert (cur_block_alloc == 0);
 		g_assert (cur_block == NULL);
@@ -156,7 +180,7 @@ tracker_db_journal_init (void)
 
 		write (fileno (journal), cur_block, 8);
 
-		current_size += 8;
+		cur_size += 8;
 
 		cur_block_kill ();
 	}
@@ -167,13 +191,15 @@ 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) {
+		fclose (journal);
+		journal = NULL;
+	}
 
-	g_free (filename);
-	filename = NULL;
+	g_free (journal_filename);
+	journal_filename = NULL;
 
 	return TRUE;
 }
@@ -181,48 +207,55 @@ tracker_db_journal_shutdown (void)
 gsize
 tracker_db_journal_get_size (void)
 {
-	return current_size;
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	return 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 
+	/* 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);
 
 	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);
 
@@ -233,15 +266,22 @@ tracker_db_journal_append_delete_statement (guint32      s_code,
 
 	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);
 
@@ -252,16 +292,24 @@ tracker_db_journal_append_delete_statement_code (guint32 s_code,
 
 	cur_entry_amount++;
 	cur_block_len += size;
+
+	return TRUE;
 }
 
-void
-tracker_db_journal_append_insert_statement (guint32      s_code, 
-                                            guint32      p_code, 
+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);
 
@@ -272,15 +320,22 @@ tracker_db_journal_append_insert_statement (guint32      s_code,
 
 	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);
 
@@ -291,15 +346,23 @@ tracker_db_journal_append_insert_statement_code (guint32 s_code,
 
 	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);
 
@@ -309,23 +372,33 @@ tracker_db_journal_append_resource (guint32      s_code,
 
 	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_assert (journal);
+	g_return_val_if_fail (journal != NULL, FALSE);
+
+	begin_pos = 0;
+	size = sizeof (guint32);
+	offset = sizeof (guint32) * 3;
 
 	cur_block_maybe_expand (size);
 
@@ -341,244 +414,368 @@ tracker_db_journal_commit_transaction (void)
 	crc = tracker_crc32 (cur_block + offset, cur_block_len - offset);
 	cur_setnum (cur_block, &begin_pos, crc);
 
-	write (fileno (journal), cur_block, cur_block_len);
-
-	current_size += cur_block_len;
+	/* FIXME: What if we don't write all of len, needs improving. */
+	if (write (fileno (journal), cur_block, cur_block_len) == -1) {
+		g_critical ("Could not write to journal, %s", g_strerror (errno));
+		return FALSE;
+	}
 
+	cur_size += 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)) == 0;
 }
 
 /*
  * Reader API
  */
-
 gboolean
-tracker_db_journal_entry_init (void)
+tracker_db_journal_reader_init (const gchar *filename)
 {
-	const gchar *journal_filename;
+	GError *error = NULL;
+	gchar *filename_used;
+
+	g_return_val_if_fail (reader.file == NULL, FALSE);
+
+	/* Used mostly for testing */
+	if (G_UNLIKELY (filename)) {
+		filename_used = g_strdup (filename);
+	} else {
+		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);
 
-	journal_filename = tracker_db_journal_filename ();
+	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 (journal_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;
+}
+
+gboolean
+tracker_db_journal_reader_shutdown (void)
+{
+	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_code = 0;
+	reader.p_code = 0;
+	reader.o_code = 0;
+	reader.object = NULL;
 
 	return TRUE;
 }
 
 TrackerDBJournalEntryType
-tracker_db_journal_entry_get_type (void)
+tracker_db_journal_reader_get_type (void)
 {
-	return journal_reader.type;
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+
+	return reader.type;
 }
 
 gboolean
-tracker_db_journal_entry_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) {
+	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;
 		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;
+		data_format = read_uint32 (reader.current);
+		reader.current += 4;
 
 		if (data_format == 1) {
-			journal_reader.type = TRACKER_DB_JOURNAL_RESOURCE;
+			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_code = read_uint32 (journal_reader.current);
-			journal_reader.current += 4;
+			reader.s_code = 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_CODE;
+					reader.type = TRACKER_DB_JOURNAL_DELETE_STATEMENT_CODE;
 				} 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_CODE;
+					reader.type = TRACKER_DB_JOURNAL_INSERT_STATEMENT_CODE;
 				} 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_code = read_uint32 (journal_reader.current);
-			journal_reader.current += 4;
+			reader.s_code = read_uint32 (reader.current);
+			reader.current += 4;
 
-			journal_reader.p_code = read_uint32 (journal_reader.current);
-			journal_reader.current += 4;
+			reader.p_code = read_uint32 (reader.current);
+			reader.current += 4;
 
 			if (data_format & 2) {
-				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) for data format 2",
+					             (gint) (reader.end - reader.current));
 					return FALSE;
 				}
 
-				journal_reader.o_code = read_uint32 (journal_reader.current);
-				journal_reader.current += 4;
+				reader.o_code = 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;
 }
 
 gboolean
-tracker_db_journal_entry_get_resource (guint32      *code,
-                                       const gchar **uri)
+tracker_db_journal_reader_get_resource (guint32      *code,
+                                        const gchar **uri)
 {
-	g_return_val_if_fail (journal_reader.type == TRACKER_DB_JOURNAL_RESOURCE, FALSE);
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+	g_return_val_if_fail (reader.type == TRACKER_DB_JOURNAL_RESOURCE, FALSE);
 
-	*code = journal_reader.s_code;
-	*uri = journal_reader.uri;
+	*code = reader.s_code;
+	*uri = reader.uri;
 
 	return TRUE;
 }
 
 gboolean
-tracker_db_journal_entry_get_statement (guint32      *s_code,
-                                        guint32      *p_code,
-                                        const gchar **object)
+tracker_db_journal_reader_get_statement (guint32      *s_code,
+                                         guint32      *p_code,
+                                         const gchar **object)
 {
-	g_return_val_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_code = journal_reader.s_code;
-	*p_code = journal_reader.p_code;
-	*object = journal_reader.object;
+	*s_code = reader.s_code;
+	*p_code = reader.p_code;
+	*object = reader.object;
 
 	return TRUE;
 }
 
 gboolean
-tracker_db_journal_entry_get_statement_code (guint32 *s_code,
-                                             guint32 *p_code,
-                                             guint32 *o_code)
+tracker_db_journal_reader_get_statement_code (guint32 *s_code,
+                                              guint32 *p_code,
+                                              guint32 *o_code)
 {
-	g_return_val_if_fail (journal_reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT_CODE ||
-	                      journal_reader.type == TRACKER_DB_JOURNAL_DELETE_STATEMENT_CODE,
+	g_return_val_if_fail (reader.file != NULL, FALSE);
+	g_return_val_if_fail (reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT_CODE ||
+	                      reader.type == TRACKER_DB_JOURNAL_DELETE_STATEMENT_CODE,
 	                      FALSE);
 
-	*s_code = journal_reader.s_code;
-	*p_code = journal_reader.p_code;
-	*o_code = journal_reader.o_code;
+	*s_code = reader.s_code;
+	*p_code = reader.p_code;
+	*o_code = reader.o_code;
 
 	return TRUE;
 }
diff --git a/src/libtracker-db/tracker-db-journal.h b/src/libtracker-db/tracker-db-journal.h
index 2bf68da..8894ebe 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,52 +41,53 @@ 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
  */
-
-gboolean     tracker_db_journal_entry_init                   (void);
+gboolean     tracker_db_journal_reader_init                  (const gchar  *filename);
+gboolean     tracker_db_journal_reader_shutdown              (void);
 TrackerDBJournalEntryType
-             tracker_db_journal_entry_get_type               (void);
+             tracker_db_journal_reader_get_type              (void);
 
-gboolean     tracker_db_journal_entry_next                   (void);
-gboolean     tracker_db_journal_entry_get_resource           (guint32      *code,
+gboolean     tracker_db_journal_reader_next                  (GError      **error);
+gboolean     tracker_db_journal_reader_get_resource          (guint32      *code,
                                                               const gchar **uri);
-gboolean     tracker_db_journal_entry_get_statement          (guint32      *s_code,
+gboolean     tracker_db_journal_reader_get_statement         (guint32      *s_code,
                                                               guint32      *p_code,
                                                               const gchar **object);
-gboolean     tracker_db_journal_entry_get_statement_code     (guint32      *s_code,
+gboolean     tracker_db_journal_reader_get_statement_code    (guint32      *s_code,
                                                               guint32      *p_code,
                                                               guint32      *o_code);
 
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..4db0916 100644
--- a/tests/libtracker-db/tracker-db-journal.c
+++ b/tests/libtracker-db/tracker-db-journal.c
@@ -17,44 +17,148 @@
  * 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;
+	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 */
+	result = tracker_db_journal_reader_init (path);
+	g_assert_cmpint (result, ==, TRUE);
+
+	type = tracker_db_journal_reader_get_type ();
+	g_assert_cmpint (type, ==, TRACKER_DB_JOURNAL_START);
+
+	result = tracker_db_journal_reader_next (&error);
+	g_assert_no_error (error);
+	g_assert_cmpint (result, ==, TRUE);
+
+	/* FIXME: unfinished */
+
+	result = tracker_db_journal_reader_shutdown ();
+	g_assert_cmpint (result, ==, TRUE);
+
+	g_free (path);
 }
 
 int
@@ -66,8 +170,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]