[tracker/journal-rotation] Implemented backup() using tar, squash with next which will implement restore() too
- From: Philip Van Hoof <pvanhoof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/journal-rotation] Implemented backup() using tar, squash with next which will implement restore() too
- Date: Fri, 7 May 2010 11:32:49 +0000 (UTC)
commit 45173d79fb4584b7cda0a1916bbb2bb30624fdb0
Author: Philip Van Hoof <philip codeminded be>
Date: Fri May 7 13:31:04 2010 +0200
Implemented backup() using tar, squash with next which will implement restore() too
configure.ac | 7 +
src/libtracker-common/tracker-os-dependant-unix.c | 4 +-
src/libtracker-data/tracker-data-backup.c | 236 +++++++++++++++++++--
src/libtracker-db/tracker-db-journal.c | 9 +-
src/libtracker-db/tracker-db-journal.h | 1 +
src/libtracker-db/tracker-db-manager.c | 4 +-
6 files changed, 233 insertions(+), 28 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 562ac15..fac9e20 100644
--- a/configure.ac
+++ b/configure.ac
@@ -227,6 +227,13 @@ fi
AM_CONDITIONAL(HAVE_ENCA, test "$have_enca" = "yes")
+# We need tar for Backup and Restore support
+AC_PATH_PROG(TAR, tar, tar)
+if test -z $TAR; then
+ AC_MSG_ERROR([Could not find 'tar'])
+fi
+AC_DEFINE_UNQUOTED(TAR, "$TAR", [The tar program])
+
AC_PATH_PROG(VALAC, valac, valac)
AC_SUBST(VALAC)
diff --git a/src/libtracker-common/tracker-os-dependant-unix.c b/src/libtracker-common/tracker-os-dependant-unix.c
index 70dd389..0c8f5ea 100644
--- a/src/libtracker-common/tracker-os-dependant-unix.c
+++ b/src/libtracker-common/tracker-os-dependant-unix.c
@@ -90,8 +90,8 @@ tracker_spawn (gchar **argv,
gboolean
tracker_spawn_async_with_channels (const gchar **argv,
- gint timeout,
- GPid *pid,
+ gint timeout,
+ GPid *pid,
GIOChannel **stdin_channel,
GIOChannel **stdout_channel,
GIOChannel **stderr_channel)
diff --git a/src/libtracker-data/tracker-data-backup.c b/src/libtracker-data/tracker-data-backup.c
index 3c5c2f5..aef4bb4 100644
--- a/src/libtracker-data/tracker-data-backup.c
+++ b/src/libtracker-data/tracker-data-backup.c
@@ -25,6 +25,7 @@
#include <libtracker-db/tracker-db-manager.h>
#include <libtracker-db/tracker-db-journal.h>
#include <libtracker-data/tracker-data-manager.h>
+#include <libtracker-common/tracker-os-dependant.h>
#include "tracker-data-backup.h"
@@ -36,6 +37,17 @@ typedef struct {
GError *error;
} BackupSaveInfo;
+typedef struct {
+ GPid pid;
+ guint stdout_watch_id;
+ guint stderr_watch_id;
+ GIOChannel *stdin_channel;
+ GIOChannel *stdout_channel;
+ GIOChannel *stderr_channel;
+ gpointer data;
+ GString *lines;
+} ProcessContext;
+
GQuark
tracker_data_backup_error_quark (void)
{
@@ -63,22 +75,139 @@ free_backup_save_info (BackupSaveInfo *info)
}
static void
-on_journal_copied (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+on_journal_copied (BackupSaveInfo *info, GError *error)
{
- BackupSaveInfo *info = user_data;
- GError *error = NULL;
-
- g_file_copy_finish (info->journal, res, &error);
-
if (info->callback) {
info->callback (error, info->user_data);
}
free_backup_save_info (info);
+}
+
+
+
+static void
+process_context_destroy (ProcessContext *context, GError *error)
+{
+ on_journal_copied (context->data, error);
+
+ if (context->lines) {
+ g_string_free (context->lines, TRUE);
+ }
+
+ if (context->stdin_channel) {
+ g_io_channel_shutdown (context->stdin_channel, FALSE, NULL);
+ g_io_channel_unref (context->stdin_channel);
+ context->stdin_channel = NULL;
+ }
+
+ if (context->stdout_watch_id != 0) {
+ g_source_remove (context->stdout_watch_id);
+ context->stdout_watch_id = 0;
+ }
+
+ if (context->stdout_channel) {
+ g_io_channel_shutdown (context->stdout_channel, FALSE, NULL);
+ g_io_channel_unref (context->stdout_channel);
+ context->stdout_channel = NULL;
+ }
+
+ if (context->stderr_watch_id != 0) {
+ g_source_remove (context->stderr_watch_id);
+ context->stderr_watch_id = 0;
+ }
+
+ if (context->stderr_channel) {
+ g_io_channel_shutdown (context->stderr_channel, FALSE, NULL);
+ g_io_channel_unref (context->stderr_channel);
+ context->stderr_channel = NULL;
+ }
+
+ if (context->pid != 0) {
+ g_spawn_close_pid (context->pid);
+ context->pid = 0;
+ }
+
+ g_free (context);
+}
+
+static gboolean
+read_line_of_tar_output (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ ProcessContext *context;
+
+ context = user_data;
+
+ if (condition & G_IO_ERR || condition & G_IO_HUP) {
+ return FALSE;
+ }
- g_clear_error (&error);
+ /* TODO: progress support */
+ return TRUE;
+}
+
+static gboolean
+read_error_of_tar_output (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ ProcessContext *context;
+ GIOStatus status;
+ gchar *line;
+
+ context = user_data;
+ status = G_IO_STATUS_NORMAL;
+
+ if (condition & G_IO_IN || condition & G_IO_PRI) {
+ do {
+ GError *error = NULL;
+
+ status = g_io_channel_read_line (channel, &line, NULL, NULL, &error);
+
+ if (status == G_IO_STATUS_NORMAL) {
+ if (context->lines == NULL)
+ context->lines = g_string_new (NULL);
+ g_string_append (context->lines, line);
+ g_free (line);
+ } else if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+ } while (status == G_IO_STATUS_NORMAL);
+
+ if (status == G_IO_STATUS_EOF ||
+ status == G_IO_STATUS_ERROR) {
+ return FALSE;
+ }
+ }
+
+ if (condition & G_IO_ERR || condition & G_IO_HUP) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+process_context_child_watch_cb (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ ProcessContext *context;
+ GError *error = NULL;
+
+ g_debug ("Process '%d' exited with code %d", pid, status);
+
+ context = (ProcessContext *) user_data;
+
+ if (context->lines) {
+ g_set_error (&error, TRACKER_DATA_BACKUP_ERROR, 0,
+ "%s", context->lines->str);
+ }
+
+ process_context_destroy (context, error);
}
void
@@ -88,6 +217,16 @@ tracker_data_backup_save (GFile *destination,
GDestroyNotify destroy)
{
BackupSaveInfo *info;
+ ProcessContext *context;
+ gchar **argv;
+ gchar *path, *directory;
+ GDir *journal_dir;
+ GFile *parent;
+ GIOChannel *stdin_channel, *stdout_channel, *stderr_channel;
+ GPid pid;
+ GPtrArray *files;
+ const gchar *f_name;
+ guint i;
info = g_new0 (BackupSaveInfo, 1);
info->destination = g_object_ref (destination);
@@ -96,16 +235,77 @@ tracker_data_backup_save (GFile *destination,
info->user_data = user_data;
info->destroy = destroy;
- /* It's fine to copy this asynchronous: the journal replay code can or
- * should cope with unfinished entries at the end of the file, while
- * restoring a backup made this way. */
+ parent = g_file_get_parent (info->journal);
+ directory = g_file_get_path (parent);
+ g_object_unref (parent);
+ path = g_file_get_path (destination);
+
+ journal_dir = g_dir_open (directory, 0, NULL);
+ f_name = g_dir_read_name (journal_dir);
+ files = g_ptr_array_new ();
+
+ while (f_name) {
+ if (f_name) {
+ if (!g_str_has_prefix (f_name, TRACKER_DB_JOURNAL_FILENAME ".")) {
+ f_name = g_dir_read_name (journal_dir);
+ continue;
+ }
+ g_ptr_array_add (files, g_strdup (f_name));
+ }
+ f_name = g_dir_read_name (journal_dir);
+ }
+
+ g_dir_close (journal_dir);
+
+ argv = g_new0 (gchar*, files->len + 7);
+
+ argv[0] = g_strdup (TAR);
+ argv[1] = g_strdup ("-zcf");
+ argv[2] = path;
+ argv[3] = g_strdup ("-C");
+ argv[4] = directory;
+ argv[5] = g_strdup (TRACKER_DB_JOURNAL_FILENAME);
+
+ for (i = 0; i < files->len; i++) {
+ argv[i+6] = g_ptr_array_index (files, i);
+ }
+
+ if (!tracker_spawn_async_with_channels ((const gchar **) argv,
+ 0, &pid,
+ &stdin_channel,
+ &stdout_channel,
+ &stderr_channel)) {
+ GError *error = NULL;
+ g_set_error (&error, TRACKER_DATA_BACKUP_ERROR, 0,
+ "Error starting tar program");
+ on_journal_copied (info, error);
+ g_strfreev (argv);
+ g_error_free (error);
+ return;
+ }
+
+ context = g_new0 (ProcessContext, 1);
+ context->lines = NULL;
+ context->data = info;
+ context->pid = pid;
+ context->stdin_channel = stdin_channel;
+ context->stderr_channel = stderr_channel;
+ context->stdout_watch_id = g_io_add_watch (stdout_channel,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
+ read_line_of_tar_output,
+ context);
+ context->stderr_watch_id = g_io_add_watch (stderr_channel,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
+ read_error_of_tar_output,
+ context);
+
+ g_child_watch_add (context->pid, process_context_child_watch_cb, context);
+
+ g_strfreev (argv);
+
+ g_debug ("Process '%d' spawned for command:'%s %s %s'",
+ pid, argv[0], argv[1], argv[2]);
- g_file_copy_async (info->journal, info->destination,
- G_FILE_COPY_OVERWRITE,
- G_PRIORITY_HIGH,
- NULL, NULL, NULL,
- on_journal_copied,
- info);
}
static gboolean
diff --git a/src/libtracker-db/tracker-db-journal.c b/src/libtracker-db/tracker-db-journal.c
index 8fc34f5..5db144d 100644
--- a/src/libtracker-db/tracker-db-journal.c
+++ b/src/libtracker-db/tracker-db-journal.c
@@ -43,7 +43,6 @@
#include "tracker-db-journal.h"
-#define JOURNAL_FILENAME "tracker-store.journal"
#define MIN_BLOCK_SIZE 1024
/*
@@ -291,7 +290,7 @@ tracker_db_journal_init (const gchar *filename,
writer.journal_filename = g_build_filename (g_get_user_data_dir (),
"tracker",
"data",
- JOURNAL_FILENAME,
+ TRACKER_DB_JOURNAL_FILENAME,
NULL);
}
@@ -655,7 +654,7 @@ tracker_db_journal_rotate (void)
if (f_name) {
- if (!g_str_has_prefix (f_name, "tracker-store.journal.")) {
+ if (!g_str_has_prefix (f_name, TRACKER_DB_JOURNAL_FILENAME ".")) {
f_name = g_dir_read_name (journal_dir);
continue;
}
@@ -666,7 +665,7 @@ tracker_db_journal_rotate (void)
cur = atoi (ptr);
max = MAX (cur, max);
}
- }
+ }
f_name = g_dir_read_name (journal_dir);
}
@@ -775,7 +774,7 @@ tracker_db_journal_reader_init (const gchar *filename)
filename_used = g_build_filename (g_get_user_data_dir (),
"tracker",
"data",
- JOURNAL_FILENAME,
+ TRACKER_DB_JOURNAL_FILENAME,
NULL);
}
diff --git a/src/libtracker-db/tracker-db-journal.h b/src/libtracker-db/tracker-db-journal.h
index 4ef0ca5..fefd515 100644
--- a/src/libtracker-db/tracker-db-journal.h
+++ b/src/libtracker-db/tracker-db-journal.h
@@ -29,6 +29,7 @@ G_BEGIN_DECLS
#define TRACKER_DB_JOURNAL_ERROR_DOMAIN "TrackerDBJournal"
#define TRACKER_DB_JOURNAL_ERROR tracker_db_journal_error_quark()
+#define TRACKER_DB_JOURNAL_FILENAME "tracker-store.journal"
typedef enum {
TRACKER_DB_JOURNAL_START,
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index fcc8d82..39ced81 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -440,15 +440,13 @@ db_manager_remove_all (gboolean rm_journal)
gchar *fullpath;
if (f_name) {
- if (!g_str_has_prefix (f_name, "tracker-store.journal.")) {
+ if (!g_str_has_prefix (f_name, TRACKER_DB_JOURNAL_FILENAME ".")) {
f_name = g_dir_read_name (journal_dir);
continue;
}
-
}
fullpath = g_build_filename (directory, f_name, NULL);
-
file = g_file_new_for_path (fullpath);
g_file_delete (file, NULL, NULL);
g_object_unref (file);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]