[gnome-documents/wip/skydrive: 1/2] miner: Add a skeleton Skydrive miner based on libzapojit
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents/wip/skydrive: 1/2] miner: Add a skeleton Skydrive miner based on libzapojit
- Date: Wed, 23 May 2012 15:30:55 +0000 (UTC)
commit 86c41cb75ea1ca5d3a0e3e6581efea3db8151f1e
Author: Debarshi Ray <debarshir gnome org>
Date: Tue May 22 17:30:45 2012 +0200
miner: Add a skeleton Skydrive miner based on libzapojit
Fixes: https://bugzilla.gnome.org/666535
configure.ac | 1 +
src/Makefile-miner.am | 22 ++
src/miner/gd-zpj-miner.c | 709 ++++++++++++++++++++++++++++++++++++++++++++
src/miner/gd-zpj-miner.h | 80 +++++
src/miner/zpj-miner-main.c | 247 +++++++++++++++
5 files changed, 1059 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d676476..fb2b031 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,6 +78,7 @@ PKG_CHECK_MODULES(MINER,
gio-2.0 >= $GLIB_MIN_VERSION
goa-1.0 >= $GOA_MIN_VERSION
libgdata >= $GDATA_MIN_VERSION
+ zapojit-0.0
oauth)
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
diff --git a/src/Makefile-miner.am b/src/Makefile-miner.am
index b70efea..d880443 100644
--- a/src/Makefile-miner.am
+++ b/src/Makefile-miner.am
@@ -19,3 +19,25 @@ gd_tracker_gdata_miner_LDADD = \
$(MINER_LIBS) \
$(DOCUMENTS_LIBS) \
$(NULL)
+
+libexec_PROGRAMS += gd-tracker-zpj-miner
+
+gd_tracker_zpj_miner_SOURCES = \
+ miner/zpj-miner-main.c \
+ miner/gd-zpj-miner.c \
+ miner/gd-zpj-miner.h \
+ $(NULL)
+
+gd_tracker_zpj_miner_CFLAGS = \
+ -DG_DISABLE_DEPRECATED \
+ -DGOA_API_IS_SUBJECT_TO_CHANGE \
+ -I$(top_srcdir)/src/lib \
+ $(MINER_CFLAGS) \
+ $(DOCUMENTS_CFLAGS) \
+ $(NULL)
+
+gd_tracker_zpj_miner_LDADD = \
+ libgdprivate-1.0.la \
+ $(MINER_LIBS) \
+ $(DOCUMENTS_LIBS) \
+ $(NULL)
diff --git a/src/miner/gd-zpj-miner.c b/src/miner/gd-zpj-miner.c
new file mode 100644
index 0000000..28f995f
--- /dev/null
+++ b/src/miner/gd-zpj-miner.c
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Gnome Documents is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Gnome Documents is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ *
+ */
+
+#include <goa/goa.h>
+#include <zpj/zpj.h>
+#include <unistd.h>
+
+#include "gd-zpj-miner.h"
+#include "gd-utils.h"
+
+#define MINER_IDENTIFIER "gd:zpj:miner:30058620-777c-47a3-a19c-a6cdf4a315c4"
+
+G_DEFINE_TYPE (GdZpjMiner, gd_zpj_miner, G_TYPE_OBJECT)
+
+struct _GdZpjMinerPrivate {
+ GoaClient *client;
+ TrackerSparqlConnection *connection;
+
+ GCancellable *cancellable;
+ GSimpleAsyncResult *result;
+
+ GList *pending_jobs;
+};
+
+typedef struct {
+ GdZpjMiner *self;
+ TrackerSparqlConnection *connection; /* borrowed from GdZpjMiner */
+ gulong miner_cancellable_id;
+
+ GoaAccount *account;
+ ZpjSkydrive *service;
+ GSimpleAsyncResult *async_result;
+ GCancellable *cancellable;
+
+ GHashTable *previous_resources;
+} AccountMinerJob;
+
+static void
+miner_cancellable_cancelled_cb (GCancellable *cancellable,
+ gpointer user_data)
+{
+ AccountMinerJob *job = user_data;
+
+ /* forward the cancel signal to the ongoing job */
+ g_cancellable_cancel (job->cancellable);
+}
+
+static void
+account_miner_job_free (AccountMinerJob *job)
+{
+ if (job->miner_cancellable_id != 0)
+ g_cancellable_disconnect (job->self->priv->cancellable,
+ job->miner_cancellable_id);
+
+ g_clear_object (&job->service);
+ g_clear_object (&job->self);
+ g_clear_object (&job->account);
+ g_clear_object (&job->async_result);
+
+ g_hash_table_unref (job->previous_resources);
+
+ g_slice_free (AccountMinerJob, job);
+}
+
+static AccountMinerJob *
+account_miner_job_new (GdZpjMiner *self,
+ GoaObject *object)
+{
+ AccountMinerJob *retval;
+ ZpjGoaAuthorizer *authorizer;
+ GoaAccount *account;
+
+ account = goa_object_get_account (object);
+ g_assert (account != NULL);
+
+ retval = g_slice_new0 (AccountMinerJob);
+ retval->self = g_object_ref (self);
+ retval->cancellable = g_cancellable_new ();
+ retval->account = account;
+ retval->connection = self->priv->connection;
+ retval->previous_resources =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, (GDestroyNotify) g_free);
+
+ if (self->priv->cancellable != NULL)
+ retval->miner_cancellable_id =
+ g_cancellable_connect (self->priv->cancellable,
+ G_CALLBACK (miner_cancellable_cancelled_cb),
+ retval, NULL);
+
+ authorizer = zpj_goa_authorizer_new (object);
+ retval->service = zpj_skydrive_new (ZPJ_AUTHORIZER (authorizer));
+
+ /* the service takes ownership of the authorizer */
+ g_object_unref (authorizer);
+
+ return retval;
+}
+
+static void
+previous_resources_cleanup_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ const gchar *resource = value;
+ GString *delete = user_data;
+
+ g_string_append_printf (delete, "<%s> a rdfs:Resource . ", resource);
+}
+
+static void
+account_miner_job_cleanup_previous (AccountMinerJob *job,
+ GError **error)
+{
+ GString *delete;
+
+ delete = g_string_new (NULL);
+ g_string_append (delete, "DELETE { ");
+
+ /* the resources left here are those who were in the database,
+ * but were not found during the query; remove them from the database.
+ */
+ g_hash_table_foreach (job->previous_resources,
+ previous_resources_cleanup_foreach,
+ delete);
+
+ g_string_append (delete, "}");
+
+ tracker_sparql_connection_update (job->connection,
+ delete->str,
+ G_PRIORITY_DEFAULT,
+ job->cancellable,
+ error);
+
+ g_string_free (delete, TRUE);
+}
+
+static void
+account_miner_job_query_zpj (AccountMinerJob *job,
+ GError **error)
+{
+}
+
+
+static void
+account_miner_job_query_existing (AccountMinerJob *job,
+ GError **error)
+{
+ GString *select;
+ TrackerSparqlCursor *cursor;
+
+ select = g_string_new (NULL);
+ g_string_append_printf (select,
+ "SELECT ?urn nao:identifier(?urn) WHERE { ?urn nie:dataSource <gd:goa-account:%s> }",
+ goa_account_get_id (job->account));
+
+ cursor = tracker_sparql_connection_query (job->connection,
+ select->str,
+ job->cancellable,
+ error);
+ g_string_free (select, TRUE);
+
+ if (cursor == NULL)
+ return;
+
+ while (tracker_sparql_cursor_next (cursor, job->cancellable, error))
+ {
+ g_hash_table_insert (job->previous_resources,
+ g_strdup (tracker_sparql_cursor_get_string (cursor, 1, NULL)),
+ g_strdup (tracker_sparql_cursor_get_string (cursor, 0, NULL)));
+ }
+
+ g_object_unref (cursor);
+}
+
+static void
+account_miner_job_ensure_datasource (AccountMinerJob *job,
+ GError **error)
+{
+ GString *datasource_insert;
+
+ datasource_insert = g_string_new (NULL);
+ g_string_append_printf (datasource_insert,
+ "INSERT OR REPLACE { <gd:goa-account:%s> a nie:DataSource ; nao:identifier \"%s\" }",
+ goa_account_get_id (job->account), MINER_IDENTIFIER);
+
+ tracker_sparql_connection_update (job->connection,
+ datasource_insert->str,
+ G_PRIORITY_DEFAULT,
+ job->cancellable,
+ error);
+
+ g_string_free (datasource_insert, TRUE);
+}
+
+static gboolean
+account_miner_job (GIOSchedulerJob *sched_job,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ AccountMinerJob *job = user_data;
+ GError *error = NULL;
+
+ account_miner_job_ensure_datasource (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ account_miner_job_query_existing (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ account_miner_job_query_zpj (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ account_miner_job_cleanup_previous (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ out:
+ if (error != NULL)
+ g_simple_async_result_take_error (job->async_result, error);
+
+ g_simple_async_result_complete_in_idle (job->async_result);
+
+ return FALSE;
+}
+
+static void
+account_miner_job_process_async (AccountMinerJob *job,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_assert (job->async_result == NULL);
+
+ job->async_result = g_simple_async_result_new (NULL, callback, user_data,
+ account_miner_job_process_async);
+ g_simple_async_result_set_op_res_gpointer (job->async_result, job, NULL);
+
+ g_io_scheduler_push_job (account_miner_job, job, NULL,
+ G_PRIORITY_DEFAULT,
+ job->cancellable);
+}
+
+static gboolean
+account_miner_job_process_finish (GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple_res = G_SIMPLE_ASYNC_RESULT (res);
+
+ g_assert (g_simple_async_result_is_valid (res, NULL,
+ account_miner_job_process_async));
+
+ if (g_simple_async_result_propagate_error (simple_res, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+gd_zpj_miner_complete_error (GdZpjMiner *self,
+ GError *error)
+{
+ g_assert (self->priv->result != NULL);
+
+ g_simple_async_result_take_error (self->priv->result, error);
+ g_simple_async_result_complete_in_idle (self->priv->result);
+}
+
+static void
+gd_zpj_miner_check_pending_jobs (GdZpjMiner *self)
+{
+ if (g_list_length (self->priv->pending_jobs) == 0)
+ g_simple_async_result_complete_in_idle (self->priv->result);
+}
+
+static void
+miner_job_process_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ AccountMinerJob *job = user_data;
+ GdZpjMiner *self = job->self;
+ GError *error = NULL;
+
+ account_miner_job_process_finish (res, &error);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error while refreshing account %s: %s",
+ goa_account_get_id (job->account), error->message);
+
+ g_error_free (error);
+ }
+
+ self->priv->pending_jobs = g_list_remove (self->priv->pending_jobs,
+ job);
+ account_miner_job_free (job);
+
+ gd_zpj_miner_check_pending_jobs (self);
+}
+
+static void
+gd_zpj_miner_setup_account (GdZpjMiner *self,
+ GoaObject *object)
+{
+ AccountMinerJob *job;
+
+ job = account_miner_job_new (self, object);
+ self->priv->pending_jobs = g_list_prepend (self->priv->pending_jobs, job);
+
+ account_miner_job_process_async (job, miner_job_process_ready_cb, job);
+}
+
+typedef struct {
+ GdZpjMiner *self;
+ GList *doc_objects;
+ GList *acc_objects;
+ GList *old_datasources;
+} CleanupJob;
+
+static gboolean
+cleanup_old_accounts_done (gpointer data)
+{
+ CleanupJob *job = data;
+ GList *l;
+ GoaObject *object;
+ GdZpjMiner *self = job->self;
+
+ /* now setup all the current accounts */
+ for (l = job->doc_objects; l != NULL; l = l->next)
+ {
+ object = l->data;
+ gd_zpj_miner_setup_account (self, object);
+
+ g_object_unref (object);
+ }
+
+ if (job->doc_objects != NULL)
+ {
+ g_list_free (job->doc_objects);
+ job->doc_objects = NULL;
+ }
+
+ if (job->acc_objects != NULL)
+ {
+ g_list_free_full (job->acc_objects, g_object_unref);
+ job->acc_objects = NULL;
+ }
+
+ if (job->old_datasources != NULL)
+ {
+ g_list_free_full (job->old_datasources, g_free);
+ job->old_datasources = NULL;
+ }
+
+ gd_zpj_miner_check_pending_jobs (self);
+
+ g_clear_object (&job->self);
+ g_slice_free (CleanupJob, job);
+
+ return FALSE;
+}
+
+static void
+cleanup_job_do_cleanup (CleanupJob *job)
+{
+ GdZpjMiner *self = job->self;
+ GString *select, *update;
+ gboolean append_union = FALSE;
+ GList *l;
+ TrackerSparqlCursor *cursor;
+ GError *error = NULL;
+ const gchar *resource;
+
+ if (job->old_datasources == NULL)
+ return;
+
+ update = g_string_new (NULL);
+ g_string_append (update, "DELETE { ");
+
+ /* select all documents from the datasources we want to remove */
+ select = g_string_new (NULL);
+ g_string_append (select, "SELECT ?urn WHERE { ");
+
+ for (l = job->old_datasources; l != NULL; l = l->next)
+ {
+ resource = l->data;
+ g_debug ("Cleaning up old datasource %s", resource);
+
+ if (append_union)
+ g_string_append (select, " UNION ");
+ else
+ append_union = TRUE;
+
+ g_string_append_printf (select, "{ ?urn nie:dataSource \"%s\" }", resource);
+
+ /* also append the datasource itself to the list of resources to delete */
+ g_string_append_printf (update, "<%s> a rdfs:Resource . ", resource);
+ }
+
+ g_string_append (select, " }");
+
+ cursor = tracker_sparql_connection_query (self->priv->connection,
+ select->str,
+ self->priv->cancellable,
+ &error);
+
+ g_string_free (select, TRUE);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error while cleaning up old accounts: %s\n", error->message);
+ return;
+ }
+
+ /* gather all the documents we want to remove */
+ while (tracker_sparql_cursor_next (cursor, self->priv->cancellable, NULL))
+ {
+ resource = tracker_sparql_cursor_get_string (cursor, 0, NULL);
+ g_debug ("Cleaning up resource %s belonging to an old datasource", resource);
+
+ if (resource != NULL)
+ g_string_append_printf (update, "<%s> a rdfs:Resource . ", resource);
+ }
+
+ g_string_append (update, " }");
+ g_object_unref (cursor);
+
+ /* actually remove everything we have to remove */
+ tracker_sparql_connection_update (self->priv->connection,
+ update->str,
+ G_PRIORITY_DEFAULT,
+ self->priv->cancellable,
+ &error);
+
+ g_string_free (update, TRUE);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error while cleaning up old accounts: %s\n", error->message);
+ return;
+ }
+}
+
+static gint
+cleanup_datasource_compare (gconstpointer a,
+ gconstpointer b)
+{
+ GoaObject *object = GOA_OBJECT (a);
+ const gchar *datasource = b;
+ gint res;
+
+ GoaAccount *account;
+ gchar *object_datasource;
+
+ account = goa_object_peek_account (object);
+ g_assert (account != NULL);
+
+ object_datasource = g_strdup_printf ("gd:goa-account:%s", goa_account_get_id (account));
+ res = g_strcmp0 (datasource, object_datasource);
+
+ g_free (object_datasource);
+
+ return res;
+}
+
+static gboolean
+cleanup_job (GIOSchedulerJob *sched_job,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ GString *select;
+ GError *error = NULL;
+ TrackerSparqlCursor *cursor;
+ const gchar *datasource;
+ GList *element;
+ CleanupJob *job = user_data;
+ GdZpjMiner *self = job->self;
+
+ /* find all our datasources in the tracker DB */
+ select = g_string_new (NULL);
+ g_string_append_printf (select, "SELECT ?datasource WHERE { ?datasource a nie:DataSource . "
+ "?datasource nao:identifier \"%s\" }", MINER_IDENTIFIER);
+
+ cursor = tracker_sparql_connection_query (self->priv->connection,
+ select->str,
+ self->priv->cancellable,
+ &error);
+ g_string_free (select, TRUE);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error while cleaning up old accounts: %s\n", error->message);
+ goto out;
+ }
+
+ while (tracker_sparql_cursor_next (cursor, self->priv->cancellable, NULL))
+ {
+ /* If the source we found is not in the current list, add
+ * it to the cleanup list.
+ * Note that the objects here in the list might *not* support
+ * documents, in case the switch has been disabled in System Settings.
+ * In fact, we only remove all the account data in case the account
+ * is really removed from the panel.
+ */
+ datasource = tracker_sparql_cursor_get_string (cursor, 0, NULL);
+ element = g_list_find_custom (job->acc_objects, datasource,
+ cleanup_datasource_compare);
+
+ if (element == NULL)
+ job->old_datasources = g_list_prepend (job->old_datasources,
+ g_strdup (datasource));
+ }
+
+ g_object_unref (cursor);
+
+ /* cleanup the DB */
+ cleanup_job_do_cleanup (job);
+
+ out:
+ g_io_scheduler_job_send_to_mainloop_async (sched_job,
+ cleanup_old_accounts_done, job, NULL);
+ return FALSE;
+}
+
+static void
+gd_zpj_miner_cleanup_old_accounts (GdZpjMiner *self,
+ GList *doc_objects,
+ GList *acc_objects)
+{
+ CleanupJob *job = g_slice_new0 (CleanupJob);
+
+ job->self = g_object_ref (self);
+ job->doc_objects = doc_objects;
+ job->acc_objects = acc_objects;
+
+ g_io_scheduler_push_job (cleanup_job, job, NULL,
+ G_PRIORITY_DEFAULT,
+ self->priv->cancellable);
+}
+
+static void
+client_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GdZpjMiner *self = user_data;
+ GoaDocuments *documents;
+ GoaAccount *account;
+ GoaObject *object;
+ const gchar *provider_type;
+ GError *error = NULL;
+ GList *accounts, *doc_objects, *acc_objects, *l;
+
+ self->priv->client = goa_client_new_finish (res, &error);
+
+ if (error != NULL)
+ {
+ gd_zpj_miner_complete_error (self, error);
+ return;
+ }
+
+ doc_objects = NULL;
+ acc_objects = NULL;
+
+ accounts = goa_client_get_accounts (self->priv->client);
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ object = l->data;
+
+ account = goa_object_peek_account (object);
+ if (account == NULL)
+ continue;
+
+ provider_type = goa_account_get_provider_type (account);
+ if (g_strcmp0 (provider_type, "windows_live") != 0)
+ continue;
+
+ acc_objects = g_list_append (acc_objects, g_object_ref (object));
+
+ documents = goa_object_peek_documents (object);
+ if (documents == NULL)
+ continue;
+
+ doc_objects = g_list_append (doc_objects, g_object_ref (object));
+ }
+
+ g_list_free_full (accounts, g_object_unref);
+
+ gd_zpj_miner_cleanup_old_accounts (self, doc_objects, acc_objects);
+}
+
+static void
+sparql_connection_ready_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GdZpjMiner *self = user_data;
+
+ self->priv->connection = tracker_sparql_connection_get_finish (res, &error);
+
+ if (error != NULL)
+ {
+ gd_zpj_miner_complete_error (self, error);
+ return;
+ }
+
+ goa_client_new (self->priv->cancellable, client_ready_cb, self);
+}
+
+static void
+gd_zpj_miner_dispose (GObject *object)
+{
+ GdZpjMiner *self = GD_ZPJ_MINER (object);
+
+ if (self->priv->pending_jobs != NULL)
+ {
+ g_list_free_full (self->priv->pending_jobs,
+ (GDestroyNotify) account_miner_job_free);
+ self->priv->pending_jobs = NULL;
+ }
+
+ g_clear_object (&self->priv->client);
+ g_clear_object (&self->priv->connection);
+ g_clear_object (&self->priv->cancellable);
+ g_clear_object (&self->priv->result);
+
+ G_OBJECT_CLASS (gd_zpj_miner_parent_class)->dispose (object);
+}
+
+static void
+gd_zpj_miner_init (GdZpjMiner *self)
+{
+ self->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_ZPJ_MINER, GdZpjMinerPrivate);
+}
+
+static void
+gd_zpj_miner_class_init (GdZpjMinerClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->dispose = gd_zpj_miner_dispose;
+
+ g_type_class_add_private (klass, sizeof (GdZpjMinerPrivate));
+}
+
+GdZpjMiner *
+gd_zpj_miner_new (void)
+{
+ return g_object_new (GD_TYPE_ZPJ_MINER, NULL);
+}
+
+void
+gd_zpj_miner_refresh_db_async (GdZpjMiner *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ self->priv->result =
+ g_simple_async_result_new (G_OBJECT (self),
+ callback, user_data,
+ gd_zpj_miner_refresh_db_async);
+ self->priv->cancellable =
+ (cancellable != NULL) ? g_object_ref (cancellable) : NULL;
+
+ tracker_sparql_connection_get_async (self->priv->cancellable,
+ sparql_connection_ready_cb, self);
+}
+
+gboolean
+gd_zpj_miner_refresh_db_finish (GdZpjMiner *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple_res = G_SIMPLE_ASYNC_RESULT (res);
+
+ g_assert (g_simple_async_result_is_valid (res, G_OBJECT (self),
+ gd_zpj_miner_refresh_db_async));
+
+ if (g_simple_async_result_propagate_error (simple_res, error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/miner/gd-zpj-miner.h b/src/miner/gd-zpj-miner.h
new file mode 100644
index 0000000..20b0b2d
--- /dev/null
+++ b/src/miner/gd-zpj-miner.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Gnome Documents is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Gnome Documents is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ *
+ */
+
+#ifndef __GD_ZPJ_MINER_H__
+#define __GD_ZPJ_MINER_H__
+
+#include <libtracker-miner/tracker-miner.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_ZPJ_MINER gd_zpj_miner_get_type()
+
+#define GD_ZPJ_MINER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GD_TYPE_ZPJ_MINER, GdZpjMiner))
+
+#define GD_ZPJ_MINER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ GD_TYPE_ZPJ_MINER, GdZpjMinerClass))
+
+#define GD_IS_ZPJ_MINER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GD_TYPE_ZPJ_MINER))
+
+#define GD_IS_ZPJ_MINER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ GD_TYPE_ZPJ_MINER))
+
+#define GD_ZPJ_MINER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GD_TYPE_ZPJ_MINER, GdZpjMinerClass))
+
+typedef struct _GdZpjMiner GdZpjMiner;
+typedef struct _GdZpjMinerClass GdZpjMinerClass;
+typedef struct _GdZpjMinerPrivate GdZpjMinerPrivate;
+
+struct _GdZpjMiner {
+ GObject parent;
+
+ GdZpjMinerPrivate *priv;
+};
+
+struct _GdZpjMinerClass {
+ GObjectClass parent_class;
+};
+
+GType gd_zpj_miner_get_type(void);
+
+GdZpjMiner * gd_zpj_miner_new (void);
+
+void gd_zpj_miner_refresh_db_async (GdZpjMiner *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gd_zpj_miner_refresh_db_finish (GdZpjMiner *self,
+ GAsyncResult *res,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GD_ZPJ_MINER_H__ */
diff --git a/src/miner/zpj-miner-main.c b/src/miner/zpj-miner-main.c
new file mode 100644
index 0000000..e48f3c2
--- /dev/null
+++ b/src/miner/zpj-miner-main.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Gnome Documents is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Gnome Documents is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ *
+ */
+
+#include <glib-unix.h>
+#include <glib.h>
+
+#include "gd-zpj-miner.h"
+
+#define BUS_NAME "org.gnome.Documents.ZpjMiner"
+#define AUTOQUIT_TIMEOUT 5 /* seconds */
+
+static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='org.gnome.Documents.ZpjMiner'>"
+ " <method name='RefreshDB'>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static GDBusNodeInfo *introspection_data = NULL;
+static GCancellable *cancellable = NULL;
+static GMainLoop *loop = NULL;
+static guint name_owner_id = 0;
+static guint autoquit_id = 0;
+static gboolean refreshing = FALSE;
+
+static gboolean
+autoquit_timeout_cb (gpointer _unused)
+{
+ g_debug ("Timeout reached, quitting...");
+
+ autoquit_id = 0;
+ g_main_loop_quit (loop);
+
+ return FALSE;
+}
+
+static void
+ensure_autoquit_off (void)
+{
+ if (g_getenv ("ZPJ_MINER_PERSIST") != NULL)
+ return;
+
+ if (autoquit_id != 0)
+ {
+ g_source_remove (autoquit_id);
+ autoquit_id = 0;
+ }
+}
+
+static void
+ensure_autoquit_on (void)
+{
+ if (g_getenv ("ZPJ_MINER_PERSIST") != NULL)
+ return;
+
+ autoquit_id =
+ g_timeout_add_seconds (AUTOQUIT_TIMEOUT,
+ autoquit_timeout_cb, NULL);
+}
+
+static gboolean
+signal_handler_cb (gpointer user_data)
+{
+ GMainLoop *loop = user_data;
+
+ if (cancellable != NULL)
+ g_cancellable_cancel (cancellable);
+
+ g_main_loop_quit (loop);
+
+ return FALSE;
+}
+
+static void
+miner_refresh_db_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusMethodInvocation *invocation = user_data;
+ GError *error = NULL;
+
+ gd_zpj_miner_refresh_db_finish (GD_ZPJ_MINER (source), res, &error);
+
+ refreshing = FALSE;
+ ensure_autoquit_on ();
+
+ if (error != NULL)
+ {
+ g_printerr ("Failed to refresh the DB cache: %s\n", error->message);
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+}
+
+static void
+handle_refresh_db (GDBusMethodInvocation *invocation)
+{
+ GdZpjMiner *miner;
+
+ ensure_autoquit_off ();
+
+ /* if we're refreshing already, compress with the current request */
+ if (refreshing)
+ return;
+
+ refreshing = TRUE;
+ cancellable = g_cancellable_new ();
+ miner = gd_zpj_miner_new ();
+
+ gd_zpj_miner_refresh_db_async (miner, cancellable,
+ miner_refresh_db_ready_cb, invocation);
+
+ g_object_unref (miner);
+}
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ if (g_strcmp0 (method_name, "RefreshDB") == 0)
+ handle_refresh_db (g_object_ref (invocation));
+ else
+ g_assert_not_reached ();
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+ NULL, /* get_property */
+ NULL, /* set_property */
+};
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ g_debug ("Connected to the session bus: %s", name);
+
+ g_dbus_connection_register_object (connection,
+ "/org/gnome/Documents/ZpjMiner",
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ NULL,
+ NULL,
+ &error);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error exporting object on the session bus: %s",
+ error->message);
+ g_error_free (error);
+
+ _exit (1);
+ }
+
+ g_debug ("Object exported on the session bus");
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_debug ("Lost bus name: %s, exiting", name);
+
+ if (cancellable != NULL)
+ g_cancellable_cancel (cancellable);
+
+ name_owner_id = 0;
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_debug ("Acquired bus name: %s", name);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_type_init ();
+
+ ensure_autoquit_on ();
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_unix_signal_add_full (G_PRIORITY_DEFAULT,
+ SIGTERM,
+ signal_handler_cb,
+ loop, NULL);
+ g_unix_signal_add_full (G_PRIORITY_DEFAULT,
+ SIGINT,
+ signal_handler_cb,
+ loop, NULL);
+
+ introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+ g_assert (introspection_data != NULL);
+
+ name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ BUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ NULL, NULL);
+
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ if (name_owner_id != 0)
+ g_bus_unown_name (name_owner_id);
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]