[gnome-documents] miner: Reduce copy/pasted code with inheritance
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] miner: Reduce copy/pasted code with inheritance
- Date: Tue, 7 Aug 2012 17:46:09 +0000 (UTC)
commit 32686b5c896a8fd9343345542e3ba19341302f1f
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Aug 1 15:16:55 2012 -0300
miner: Reduce copy/pasted code with inheritance
A large amount of the code in each miner is copy/pasted. We can do
better than this. Define a base subclass that does most of the work,
and override the parts that are different in each subclass.
While we're at it, deduplicate the miner main start, as well.
https://bugzilla.gnome.org/show_bug.cgi?id=681028
src/Makefile-miner.am | 4 +
src/miner/gd-gdata-miner.c | 717 ++---------------------------------------
src/miner/gd-gdata-miner.h | 16 +-
src/miner/gd-miner.c | 656 ++++++++++++++++++++++++++++++++++++++
src/miner/gd-miner.h | 97 ++++++
src/miner/gd-zpj-miner.c | 658 ++-------------------------------------
src/miner/gd-zpj-miner.h | 16 +-
src/miner/gdata-miner-main.c | 230 +-------------
src/miner/miner-main.c | 248 +++++++++++++++
src/miner/zpj-miner-main.c | 230 +-------------
10 files changed, 1080 insertions(+), 1792 deletions(-)
---
diff --git a/src/Makefile-miner.am b/src/Makefile-miner.am
index e590a59..e282697 100644
--- a/src/Makefile-miner.am
+++ b/src/Makefile-miner.am
@@ -31,6 +31,8 @@ libexec_PROGRAMS += gd-tracker-gdata-miner
gd_tracker_gdata_miner_SOURCES = \
miner/gdata-miner-main.c \
+ miner/gd-miner.c \
+ miner/gd-miner.h \
miner/gd-gdata-miner.c \
miner/gd-gdata-miner.h \
$(NULL)
@@ -53,6 +55,8 @@ libexec_PROGRAMS += gd-tracker-zpj-miner
gd_tracker_zpj_miner_SOURCES = \
miner/zpj-miner-main.c \
+ miner/gd-miner.c \
+ miner/gd-miner.h \
miner/gd-zpj-miner.c \
miner/gd-zpj-miner.h \
$(NULL)
diff --git a/src/miner/gd-gdata-miner.c b/src/miner/gd-gdata-miner.c
index 4fd258d..d747ecb 100644
--- a/src/miner/gd-gdata-miner.c
+++ b/src/miner/gd-gdata-miner.c
@@ -21,150 +21,23 @@
#define GOA_API_IS_SUBJECT_TO_CHANGE
#include <gdata/gdata.h>
-#include <goa/goa.h>
-#include <unistd.h>
#include "gd-gdata-miner.h"
-#include "gd-miner-tracker.h"
-#include "gd-utils.h"
#define MINER_IDENTIFIER "gd:gdata:miner:86ec9bc9-c242-427f-aa19-77b5a2c9b6f0"
#define STARRED_CATEGORY_TERM "http://schemas.google.com/g/2005/labels#starred"
#define PARENT_LINK_REL "http://schemas.google.com/docs/2007#parent"
-G_DEFINE_TYPE (GdGDataMiner, gd_gdata_miner, G_TYPE_OBJECT)
-
-struct _GdGDataMinerPrivate {
- GoaClient *client;
- TrackerSparqlConnection *connection;
-
- GCancellable *cancellable;
- GSimpleAsyncResult *result;
-
- GList *pending_jobs;
-};
-
-typedef struct {
- GdGDataMiner *self;
- TrackerSparqlConnection *connection; /* borrowed from GdGDataMiner */
- gulong miner_cancellable_id;
-
- GoaAccount *account;
- GDataDocumentsService *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 (GdGDataMiner *self,
- GoaObject *object)
-{
- AccountMinerJob *retval;
- GDataGoaAuthorizer *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 = gdata_goa_authorizer_new (object);
- retval->service = gdata_documents_service_new (GDATA_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);
-}
+G_DEFINE_TYPE (GdGDataMiner, gd_gdata_miner, GD_TYPE_MINER)
static gboolean
-account_miner_job_process_entry (AccountMinerJob *job,
+account_miner_job_process_entry (GdAccountMinerJob *job,
GDataDocumentsEntry *doc_entry,
GError **error)
{
GDataEntry *entry = GDATA_ENTRY (doc_entry);
gchar *resource = NULL;
- gchar *date, *resource_url, *datasource_urn, *identifier;
+ gchar *date, *resource_url, *identifier;
const gchar *class = NULL;
GList *authors, *l, *parents = NULL;
@@ -209,24 +82,20 @@ account_miner_job_process_entry (AccountMinerJob *job,
class = "nfo:PaginatedTextDocument";
else if (GDATA_IS_DOCUMENTS_FOLDER (doc_entry))
class = "nfo:DataContainer";
-
+
resource = gd_miner_tracker_sparql_connection_ensure_resource
- (job->connection,
+ (job->connection,
job->cancellable, error,
resource_url, identifier,
"nfo:RemoteDataObject", class, NULL);
-
+
if (*error != NULL)
goto out;
- datasource_urn = g_strdup_printf ("gd:goa-account:%s",
- goa_account_get_id (job->account));
gd_miner_tracker_sparql_connection_set_triple
(job->connection, job->cancellable, error,
identifier, resource,
- "nie:dataSource", datasource_urn);
-
- g_free (datasource_urn);
+ "nie:dataSource", job->datasource_urn);
if (*error != NULL)
goto out;
@@ -235,7 +104,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
alternate_uri = gdata_link_get_uri (alternate);
gd_miner_tracker_sparql_connection_insert_or_replace_triple
- (job->connection,
+ (job->connection,
job->cancellable, error,
identifier, resource,
"nie:url", alternate_uri);
@@ -249,7 +118,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
gchar *parent_resource_urn, *parent_resource_id;
parent = l->data;
- parent_resource_id =
+ parent_resource_id =
g_strdup_printf ("gd:collection:%s", gdata_link_get_uri (parent));
parent_resource_urn = gd_miner_tracker_sparql_connection_ensure_resource
@@ -284,7 +153,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
}
gd_miner_tracker_sparql_connection_toggle_favorite
- (job->connection,
+ (job->connection,
job->cancellable, error,
resource, starred);
@@ -292,7 +161,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
goto out;
gd_miner_tracker_sparql_connection_insert_or_replace_triple
- (job->connection,
+ (job->connection,
job->cancellable, error,
identifier, resource,
"nie:description", gdata_entry_get_summary (entry));
@@ -301,7 +170,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
goto out;
gd_miner_tracker_sparql_connection_insert_or_replace_triple
- (job->connection,
+ (job->connection,
job->cancellable, error,
identifier, resource,
"nie:title", gdata_entry_get_title (entry));
@@ -325,7 +194,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
goto out;
gd_miner_tracker_sparql_connection_insert_or_replace_triple
- (job->connection,
+ (job->connection,
job->cancellable, error,
identifier, resource,
"nco:creator", contact_resource);
@@ -380,7 +249,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
date = gd_iso8601_from_timestamp (gdata_entry_get_published (entry));
gd_miner_tracker_sparql_connection_insert_or_replace_triple
- (job->connection,
+ (job->connection,
job->cancellable, error,
identifier, resource,
"nie:contentCreated", date);
@@ -391,7 +260,7 @@ account_miner_job_process_entry (AccountMinerJob *job,
date = gd_iso8601_from_timestamp (gdata_entry_get_updated (entry));
gd_miner_tracker_sparql_connection_insert_or_replace_triple
- (job->connection,
+ (job->connection,
job->cancellable, error,
identifier, resource,
"nie:contentLastModified", date);
@@ -415,8 +284,8 @@ account_miner_job_process_entry (AccountMinerJob *job,
}
static void
-account_miner_job_query_gdata (AccountMinerJob *job,
- GError **error)
+query_gdata (GdAccountMinerJob *job,
+ GError **error)
{
GDataDocumentsQuery *query;
GDataDocumentsFeed *feed;
@@ -424,8 +293,8 @@ account_miner_job_query_gdata (AccountMinerJob *job,
query = gdata_documents_query_new (NULL);
gdata_documents_query_set_show_folders (query, TRUE);
- feed = gdata_documents_service_query_documents
- (job->service, query,
+ feed = gdata_documents_service_query_documents
+ (GDATA_DOCUMENTS_SERVICE (job->service), query,
job->cancellable, NULL, NULL, error);
g_object_unref (query);
@@ -448,551 +317,35 @@ account_miner_job_query_gdata (AccountMinerJob *job,
g_object_unref (feed);
}
-
-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_gdata (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_gdata_miner_complete_error (GdGDataMiner *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_gdata_miner_check_pending_jobs (GdGDataMiner *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;
- GdGDataMiner *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_gdata_miner_check_pending_jobs (self);
-}
-
-static void
-gd_gdata_miner_setup_account (GdGDataMiner *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 {
- GdGDataMiner *self;
- GList *doc_objects;
- GList *acc_objects;
- GList *old_datasources;
-} CleanupJob;
-
-static gboolean
-cleanup_old_accounts_done (gpointer data)
+static GObject *
+create_service (GdMiner *self,
+ GoaObject *object)
{
- CleanupJob *job = data;
- GList *l;
- GoaObject *object;
- GdGDataMiner *self = job->self;
-
- /* now setup all the current accounts */
- for (l = job->doc_objects; l != NULL; l = l->next)
- {
- object = l->data;
- gd_gdata_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_gdata_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)
-{
- GdGDataMiner *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;
- GdGDataMiner *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_gdata_miner_cleanup_old_accounts (GdGDataMiner *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)
-{
- GdGDataMiner *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_gdata_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, "google") != 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_gdata_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;
- GdGDataMiner *self = user_data;
-
- self->priv->connection = tracker_sparql_connection_get_finish (res, &error);
-
- if (error != NULL)
- {
- gd_gdata_miner_complete_error (self, error);
- return;
- }
-
- goa_client_new (self->priv->cancellable, client_ready_cb, self);
-}
-
-static void
-gd_gdata_miner_dispose (GObject *object)
-{
- GdGDataMiner *self = GD_GDATA_MINER (object);
+ GDataGoaAuthorizer *authorizer;
+ GDataDocumentsService *service;
- if (self->priv->pending_jobs != NULL)
- {
- g_list_free_full (self->priv->pending_jobs,
- (GDestroyNotify) account_miner_job_free);
- self->priv->pending_jobs = NULL;
- }
+ authorizer = gdata_goa_authorizer_new (object);
+ service = gdata_documents_service_new (GDATA_AUTHORIZER (authorizer));
- g_clear_object (&self->priv->client);
- g_clear_object (&self->priv->connection);
- g_clear_object (&self->priv->cancellable);
- g_clear_object (&self->priv->result);
+ /* the service takes ownership of the authorizer */
+ g_object_unref (authorizer);
- G_OBJECT_CLASS (gd_gdata_miner_parent_class)->dispose (object);
+ return G_OBJECT (service);
}
static void
-gd_gdata_miner_init (GdGDataMiner *self)
+gd_gdata_miner_init (GdGDataMiner *miner)
{
- self->priv =
- G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_GDATA_MINER, GdGDataMinerPrivate);
}
static void
gd_gdata_miner_class_init (GdGDataMinerClass *klass)
{
- GObjectClass *oclass = G_OBJECT_CLASS (klass);
-
- oclass->dispose = gd_gdata_miner_dispose;
-
- g_type_class_add_private (klass, sizeof (GdGDataMinerPrivate));
-}
-
-GdGDataMiner *
-gd_gdata_miner_new (void)
-{
- return g_object_new (GD_TYPE_GDATA_MINER, NULL);
-}
-
-void
-gd_gdata_miner_refresh_db_async (GdGDataMiner *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- self->priv->result =
- g_simple_async_result_new (G_OBJECT (self),
- callback, user_data,
- gd_gdata_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_gdata_miner_refresh_db_finish (GdGDataMiner *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_gdata_miner_refresh_db_async));
+ GdMinerClass *miner_class = GD_MINER_CLASS (klass);
- if (g_simple_async_result_propagate_error (simple_res, error))
- return FALSE;
+ miner_class->goa_provider_type = "google";
+ miner_class->miner_identifier = MINER_IDENTIFIER;
- return TRUE;
+ miner_class->create_service = create_service;
+ miner_class->query = query_gdata;
}
diff --git a/src/miner/gd-gdata-miner.h b/src/miner/gd-gdata-miner.h
index 3e5b6b9..e42c774 100644
--- a/src/miner/gd-gdata-miner.h
+++ b/src/miner/gd-gdata-miner.h
@@ -22,8 +22,8 @@
#ifndef __GD_GDATA_MINER_H__
#define __GD_GDATA_MINER_H__
-#include <libtracker-miner/tracker-miner.h>
#include <gio/gio.h>
+#include "gd-miner.h"
G_BEGIN_DECLS
@@ -54,27 +54,17 @@ typedef struct _GdGDataMinerClass GdGDataMinerClass;
typedef struct _GdGDataMinerPrivate GdGDataMinerPrivate;
struct _GdGDataMiner {
- GObject parent;
+ GdMiner parent;
GdGDataMinerPrivate *priv;
};
struct _GdGDataMinerClass {
- GObjectClass parent_class;
+ GdMinerClass parent_class;
};
GType gd_gdata_miner_get_type(void);
-GdGDataMiner * gd_gdata_miner_new (void);
-
-void gd_gdata_miner_refresh_db_async (GdGDataMiner *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gd_gdata_miner_refresh_db_finish (GdGDataMiner *self,
- GAsyncResult *res,
- GError **error);
-
G_END_DECLS
#endif /* __GD_GDATA_MINER_H__ */
diff --git a/src/miner/gd-miner.c b/src/miner/gd-miner.c
new file mode 100644
index 0000000..8c17ea9
--- /dev/null
+++ b/src/miner/gd-miner.c
@@ -0,0 +1,656 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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: Cosimo Cecchi <cosimoc redhat com>
+ * Author: Jasper St. Pierre <jstpierre mecheye net>
+ *
+ */
+
+#include "config.h"
+
+#include "gd-miner.h"
+
+G_DEFINE_TYPE (GdMiner, gd_miner, G_TYPE_OBJECT)
+
+struct _GdMinerPrivate {
+ GoaClient *client;
+ TrackerSparqlConnection *connection;
+
+ GCancellable *cancellable;
+ GSimpleAsyncResult *result;
+
+ GList *pending_jobs;
+};
+
+static void
+gd_account_miner_job_free (GdAccountMinerJob *job)
+{
+ if (job->miner_cancellable_id != 0)
+ g_cancellable_disconnect (job->miner->priv->cancellable,
+ job->miner_cancellable_id);
+
+ g_clear_object (&job->service);
+ g_clear_object (&job->miner);
+ g_clear_object (&job->account);
+ g_clear_object (&job->async_result);
+
+ g_hash_table_unref (job->previous_resources);
+
+ g_slice_free (GdAccountMinerJob, job);
+}
+
+static void
+gd_miner_dispose (GObject *object)
+{
+ GdMiner *self = GD_MINER (object);
+
+ if (self->priv->pending_jobs != NULL)
+ {
+ g_list_free_full (self->priv->pending_jobs,
+ (GDestroyNotify) gd_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_miner_parent_class)->dispose (object);
+}
+
+static void
+gd_miner_init (GdMiner *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_MINER, GdMinerPrivate);
+}
+
+static void
+gd_miner_class_init (GdMinerClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->dispose = gd_miner_dispose;
+
+ g_type_class_add_private (klass, sizeof (GdMinerPrivate));
+}
+
+static void
+gd_miner_complete_error (GdMiner *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_miner_check_pending_jobs (GdMiner *self)
+{
+ if (g_list_length (self->priv->pending_jobs) == 0)
+ g_simple_async_result_complete_in_idle (self->priv->result);
+}
+
+static void
+gd_account_miner_job_ensure_datasource (GdAccountMinerJob *job,
+ GError **error)
+{
+ GString *datasource_insert;
+
+ datasource_insert = g_string_new (NULL);
+ g_string_append_printf (datasource_insert,
+ "INSERT OR REPLACE INTO <%s> {"
+ " <%s> a nie:DataSource ; nao:identifier \"%s\""
+ "}",
+ job->datasource_urn,
+ job->datasource_urn,
+ GD_MINER_GET_CLASS (job->miner)->miner_identifier);
+
+ tracker_sparql_connection_update (job->connection,
+ datasource_insert->str,
+ G_PRIORITY_DEFAULT,
+ job->cancellable,
+ error);
+
+ g_string_free (datasource_insert, TRUE);
+}
+
+static void
+gd_account_miner_job_query_existing (GdAccountMinerJob *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
+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
+gd_account_miner_job_cleanup_previous (GdAccountMinerJob *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
+gd_account_miner_job_query (GdAccountMinerJob *job,
+ GError **error)
+{
+ GdMinerClass *miner_class = GD_MINER_GET_CLASS (job->miner);
+
+ miner_class->query (job, error);
+}
+
+static gboolean
+gd_account_miner_job (GIOSchedulerJob *sched_job,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ GdAccountMinerJob *job = user_data;
+ GError *error = NULL;
+
+ gd_account_miner_job_ensure_datasource (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ gd_account_miner_job_query_existing (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ gd_account_miner_job_query (job, &error);
+
+ if (error != NULL)
+ goto out;
+
+ gd_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
+gd_account_miner_job_process_async (GdAccountMinerJob *job,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_assert (job->async_result == NULL);
+
+ job->async_result = g_simple_async_result_new (NULL, callback, user_data,
+ gd_account_miner_job_process_async);
+ g_simple_async_result_set_op_res_gpointer (job->async_result, job, NULL);
+
+ g_io_scheduler_push_job (gd_account_miner_job, job, NULL,
+ G_PRIORITY_DEFAULT,
+ job->cancellable);
+}
+
+static gboolean
+gd_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,
+ gd_account_miner_job_process_async));
+
+ if (g_simple_async_result_propagate_error (simple_res, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+miner_cancellable_cancelled_cb (GCancellable *cancellable,
+ gpointer user_data)
+{
+ GdAccountMinerJob *job = user_data;
+
+ /* forward the cancel signal to the ongoing job */
+ g_cancellable_cancel (job->cancellable);
+}
+
+static GdAccountMinerJob *
+gd_account_miner_job_new (GdMiner *self,
+ GoaObject *object)
+{
+ GdAccountMinerJob *retval;
+ GoaAccount *account;
+ GdMinerClass *miner_class = GD_MINER_GET_CLASS (self);
+
+ account = goa_object_get_account (object);
+ g_assert (account != NULL);
+
+ retval = g_slice_new0 (GdAccountMinerJob);
+ retval->miner = 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);
+
+ retval->service = miner_class->create_service (self, object);
+ retval->datasource_urn = g_strdup_printf ("gd:goa-account:%s",
+ goa_account_get_id (retval->account));
+
+ return retval;
+}
+
+static void
+miner_job_process_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GdAccountMinerJob *job = user_data;
+ GdMiner *self = job->miner;
+ GError *error = NULL;
+
+ gd_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);
+ gd_account_miner_job_free (job);
+
+ gd_miner_check_pending_jobs (self);
+}
+
+static void
+gd_miner_setup_account (GdMiner *self,
+ GoaObject *object)
+{
+ GdAccountMinerJob *job;
+
+ job = gd_account_miner_job_new (self, object);
+ self->priv->pending_jobs = g_list_prepend (self->priv->pending_jobs, job);
+
+ gd_account_miner_job_process_async (job, miner_job_process_ready_cb, job);
+}
+
+typedef struct {
+ GdMiner *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;
+ GdMiner *self = job->self;
+
+ /* now setup all the current accounts */
+ for (l = job->doc_objects; l != NULL; l = l->next)
+ {
+ object = l->data;
+ gd_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_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)
+{
+ GdMiner *self = job->self;
+ GList *l;
+ GString *update;
+ GError *error = NULL;
+
+ if (job->old_datasources == NULL)
+ return;
+
+ update = g_string_new (NULL);
+
+ for (l = job->old_datasources; l != NULL; l = l->next)
+ {
+ const gchar *resource;
+
+ resource = l->data;
+ g_debug ("Cleaning up old datasource %s", resource);
+
+ g_string_append_printf (update,
+ "DELETE {"
+ " ?u a rdfs:Resource"
+ "} WHERE {"
+ " GRAPH <%s> {"
+ " ?u a rdfs:Resource"
+ " }"
+ "}",
+ resource);
+ }
+
+ 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);
+ g_error_free (error);
+ }
+}
+
+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;
+ GdMiner *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\" }",
+ GD_MINER_GET_CLASS (self)->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_miner_cleanup_old_accounts (GdMiner *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)
+{
+ GdMiner *self = user_data;
+ GoaDocuments *documents;
+ GoaAccount *account;
+ GoaObject *object;
+ const gchar *provider_type;
+ GError *error = NULL;
+ GList *accounts, *doc_objects, *acc_objects, *l;
+ GdMinerClass *miner_class = GD_MINER_GET_CLASS (self);
+
+ self->priv->client = goa_client_new_finish (res, &error);
+
+ if (error != NULL)
+ {
+ gd_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, miner_class->goa_provider_type) != 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_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;
+ GdMiner *self = user_data;
+
+ self->priv->connection = tracker_sparql_connection_get_finish (res, &error);
+
+ if (error != NULL)
+ {
+ gd_miner_complete_error (self, error);
+ return;
+ }
+
+ goa_client_new (self->priv->cancellable, client_ready_cb, self);
+}
+
+void
+gd_miner_refresh_db_async (GdMiner *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ self->priv->result =
+ g_simple_async_result_new (G_OBJECT (self),
+ callback, user_data,
+ gd_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_miner_refresh_db_finish (GdMiner *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_miner_refresh_db_async));
+
+ if (g_simple_async_result_propagate_error (simple_res, error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/miner/gd-miner.h b/src/miner/gd-miner.h
new file mode 100644
index 0000000..c61135a
--- /dev/null
+++ b/src/miner/gd-miner.h
@@ -0,0 +1,97 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright (C) 2012 Red Hat
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Jasper St. Pierre <jstpierre mecheye net>
+ *
+ */
+
+
+#ifndef __GD_MINER_H__
+#define __GD_MINER_H__
+
+#include <libtracker-miner/tracker-miner.h>
+#include <glib-object.h>
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+#include "gd-miner-tracker.h"
+#include "gd-utils.h"
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_MINER (gd_miner_get_type ())
+#define GD_MINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GD_TYPE_MINER, GdMiner))
+#define GD_MINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GD_TYPE_MINER, GdMinerClass))
+#define GD_IS_MINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GD_TYPE_MINER))
+#define GD_IS_MINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GD_TYPE_MINER))
+#define GD_MINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GD_TYPE_MINER, GdMinerClass))
+
+typedef struct _GdMiner GdMiner;
+typedef struct _GdMinerClass GdMinerClass;
+typedef struct _GdMinerPrivate GdMinerPrivate;
+
+typedef struct {
+ GdMiner *miner;
+ TrackerSparqlConnection *connection; /* borrowed from GdMiner */
+ gulong miner_cancellable_id;
+
+ GoaAccount *account;
+ GObject *service;
+ GSimpleAsyncResult *async_result;
+ GCancellable *cancellable;
+
+ GHashTable *previous_resources;
+ gchar *datasource_urn;
+} GdAccountMinerJob;
+
+struct _GdMiner
+{
+ GObject parent;
+
+ GdMinerPrivate *priv;
+};
+
+struct _GdMinerClass
+{
+ GObjectClass parent_class;
+
+ char *goa_provider_type;
+ char *miner_identifier;
+
+ GObject * (*create_service) (GdMiner *self,
+ GoaObject *object);
+
+ void (*query) (GdAccountMinerJob *job,
+ GError **error);
+};
+
+GType gd_miner_get_type (void);
+
+void gd_miner_refresh_db_async (GdMiner *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gd_miner_refresh_db_finish (GdMiner *self,
+ GAsyncResult *res,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GD_MINER_H__ */
diff --git a/src/miner/gd-zpj-miner.c b/src/miner/gd-zpj-miner.c
index 280da22..976e2c3 100644
--- a/src/miner/gd-zpj-miner.c
+++ b/src/miner/gd-zpj-miner.c
@@ -22,146 +22,15 @@
#define GOA_API_IS_SUBJECT_TO_CHANGE
#include <goa/goa.h>
#include <zpj/zpj.h>
-#include <unistd.h>
#include "gd-zpj-miner.h"
-#include "gd-miner-tracker.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;
- gchar *datasource_urn;
-} 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_free (job->datasource_urn);
-
- 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);
-
- retval->datasource_urn = g_strconcat ("gd:goa-account:",
- goa_account_get_id (retval->account),
- NULL);
- 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);
-}
+G_DEFINE_TYPE (GdZpjMiner, gd_zpj_miner, GD_TYPE_MINER)
static gboolean
-account_miner_job_process_entry (AccountMinerJob *job,
+account_miner_job_process_entry (GdAccountMinerJob *job,
ZpjSkydriveEntry *entry,
GError **error)
{
@@ -324,13 +193,13 @@ account_miner_job_process_entry (AccountMinerJob *job,
}
static void
-account_miner_job_traverse_folder (AccountMinerJob *job,
+account_miner_job_traverse_folder (GdAccountMinerJob *job,
const gchar *folder_id,
GError **error)
{
GList *entries, *l;
- entries = zpj_skydrive_list_folder_id (job->service,
+ entries = zpj_skydrive_list_folder_id (ZPJ_SKYDRIVE (job->service),
folder_id,
job->cancellable,
error);
@@ -368,527 +237,44 @@ account_miner_job_traverse_folder (AccountMinerJob *job,
}
static void
-account_miner_job_query_zpj (AccountMinerJob *job,
- GError **error)
+query_zpj (GdAccountMinerJob *job,
+ GError **error)
{
account_miner_job_traverse_folder (job,
ZPJ_SKYDRIVE_FOLDER_SKYDRIVE,
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 INTO <%s> {"
- " <%s> a nie:DataSource ; nao:identifier \"%s\""
- "}",
- job->datasource_urn,
- job->datasource_urn,
- 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)
+static GObject *
+create_service (GdMiner *self,
+ GoaObject *object)
{
- 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;
- GList *l;
- GString *update;
- GError *error = NULL;
-
- if (job->old_datasources == NULL)
- return;
-
- update = g_string_new (NULL);
-
- for (l = job->old_datasources; l != NULL; l = l->next)
- {
- const gchar *resource;
-
- resource = l->data;
- g_debug ("Cleaning up old datasource %s", resource);
-
- g_string_append_printf (update,
- "DELETE {"
- " ?u a rdfs:Resource"
- "} WHERE {"
- " GRAPH <%s> {"
- " ?u a rdfs:Resource"
- " }"
- "}",
- resource);
- }
-
- 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);
- g_error_free (error);
- }
-}
-
-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);
+ ZpjGoaAuthorizer *authorizer;
+ ZpjSkydrive *service;
- if (self->priv->pending_jobs != NULL)
- {
- g_list_free_full (self->priv->pending_jobs,
- (GDestroyNotify) account_miner_job_free);
- self->priv->pending_jobs = NULL;
- }
+ authorizer = zpj_goa_authorizer_new (object);
+ service = zpj_skydrive_new (ZPJ_AUTHORIZER (authorizer));
- g_clear_object (&self->priv->client);
- g_clear_object (&self->priv->connection);
- g_clear_object (&self->priv->cancellable);
- g_clear_object (&self->priv->result);
+ /* the service takes ownership of the authorizer */
+ g_object_unref (authorizer);
- G_OBJECT_CLASS (gd_zpj_miner_parent_class)->dispose (object);
+ return G_OBJECT (service);
}
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);
+ GdMinerClass *miner_class = GD_MINER_CLASS (klass);
- oclass->dispose = gd_zpj_miner_dispose;
+ miner_class->goa_provider_type = "windows_live";
+ miner_class->miner_identifier = MINER_IDENTIFIER;
- 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;
+ miner_class->create_service = create_service;
+ miner_class->query = query_zpj;
}
diff --git a/src/miner/gd-zpj-miner.h b/src/miner/gd-zpj-miner.h
index 20b0b2d..2ece166 100644
--- a/src/miner/gd-zpj-miner.h
+++ b/src/miner/gd-zpj-miner.h
@@ -22,8 +22,8 @@
#ifndef __GD_ZPJ_MINER_H__
#define __GD_ZPJ_MINER_H__
-#include <libtracker-miner/tracker-miner.h>
#include <gio/gio.h>
+#include "gd-miner.h"
G_BEGIN_DECLS
@@ -54,27 +54,17 @@ typedef struct _GdZpjMinerClass GdZpjMinerClass;
typedef struct _GdZpjMinerPrivate GdZpjMinerPrivate;
struct _GdZpjMiner {
- GObject parent;
+ GdMiner parent;
GdZpjMinerPrivate *priv;
};
struct _GdZpjMinerClass {
- GObjectClass parent_class;
+ GdMinerClass 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/gdata-miner-main.c b/src/miner/gdata-miner-main.c
index 0a96cc9..8ecde9b 100644
--- a/src/miner/gdata-miner-main.c
+++ b/src/miner/gdata-miner-main.c
@@ -19,229 +19,11 @@
*
*/
-#include <glib-unix.h>
-#include <glib.h>
+#define INSIDE_MINER
+#define MINER_NAME "GDATA"
+#define MINER_TYPE GD_TYPE_GDATA_MINER
+#define MINER_BUS_NAME "org.gnome.Documents.GDataMiner"
+#define MINER_OBJECT_PATH "/org/gnome/Documents/GDataMiner"
#include "gd-gdata-miner.h"
-
-#define BUS_NAME "org.gnome.Documents.GDataMiner"
-#define AUTOQUIT_TIMEOUT 5 /* seconds */
-
-static const gchar introspection_xml[] =
- "<node>"
- " <interface name='org.gnome.Documents.Miner'>"
- " <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 ("GDATA_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 ("GDATA_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_gdata_miner_refresh_db_finish (GD_GDATA_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)
-{
- GdGDataMiner *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_gdata_miner_new ();
-
- gd_gdata_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/GDataMiner",
- 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;
-}
+#include "miner-main.c"
diff --git a/src/miner/miner-main.c b/src/miner/miner-main.c
new file mode 100644
index 0000000..0e2b9cd
--- /dev/null
+++ b/src/miner/miner-main.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2011 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: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef INSIDE_MINER
+#error "miner-main.c is meant to be included, not compiled standalone"
+#endif
+
+#include <glib-unix.h>
+#include <glib.h>
+
+#define AUTOQUIT_TIMEOUT 5 /* seconds */
+
+static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='org.gnome.Documents.Miner'>"
+ " <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 (MINER_NAME "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 (MINER_NAME "_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_miner_refresh_db_finish (GD_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)
+{
+ GdMiner *miner;
+
+ ensure_autoquit_off ();
+
+ /* if we're refreshing already, compress with the current request */
+ if (refreshing)
+ return;
+
+ refreshing = TRUE;
+ cancellable = g_cancellable_new ();
+ miner = g_object_new (MINER_TYPE, NULL);
+
+ gd_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,
+ MINER_OBJECT_PATH,
+ 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,
+ MINER_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;
+}
diff --git a/src/miner/zpj-miner-main.c b/src/miner/zpj-miner-main.c
index d07e529..8433eef 100644
--- a/src/miner/zpj-miner-main.c
+++ b/src/miner/zpj-miner-main.c
@@ -19,229 +19,11 @@
*
*/
-#include <glib-unix.h>
-#include <glib.h>
+#define INSIDE_MINER
+#define MINER_NAME "ZPJ"
+#define MINER_TYPE GD_TYPE_ZPJ_MINER
+#define MINER_BUS_NAME "org.gnome.Documents.ZpjMiner"
+#define MINER_OBJECT_PATH "/org/gnome/Documents/ZpjMiner"
#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.Miner'>"
- " <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;
-}
+#include "miner-main.c"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]