[gnome-online-miners] Use a gdbus-codegen-ed GDBusInterfaceSkeleton and GApplication



commit 3d70a23d4e24f524f2ad61ad259985fe746a2e8b
Author: Debarshi Ray <debarshir gnome org>
Date:   Fri Jun 20 15:19:01 2014 +0200

    Use a gdbus-codegen-ed GDBusInterfaceSkeleton and GApplication
    
    ... instead of manually acquiring the bus, registering objects on it,
    dealing with the details of handling methods and parameters,
    unwrapping parameters from GVariant, dealing with timeouts, etc..
    
    https://bugzilla.gnome.org/show_bug.cgi?id=731976

 configure.ac          |    2 +-
 src/Makefile.am       |   28 ++++++
 src/gom-application.c |  242 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/gom-application.h |   62 +++++++++++++
 src/gom-dbus.xml      |   30 ++++++
 src/gom-miner-main.c  |  234 +++--------------------------------------------
 6 files changed, 377 insertions(+), 221 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f308778..102402f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,7 +35,7 @@ LT_INIT
 PKG_CHECK_MODULES(GDATA, [libgdata >= $GDATA_MIN_VERSION])
 PKG_CHECK_MODULES(GFBGRAPH, [libgfbgraph-0.2 >= $GFBGRAPH_MIN_VERSION])
 PKG_CHECK_MODULES(GLIB, [glib-2.0 >= $GLIB_MIN_VERSION])
-PKG_CHECK_MODULES(GIO, [gio-2.0])
+PKG_CHECK_MODULES(GIO, [gio-2.0 gio-unix-2.0])
 
 PKG_CHECK_MODULES(GOA, [goa-1.0 >= $GOA_MIN_VERSION])
 AC_DEFINE([GOA_API_IS_SUBJECT_TO_CHANGE], [], [We are aware that GOA's API can change])
diff --git a/src/Makefile.am b/src/Makefile.am
index 56f5e8a..ef82626 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,17 @@
 pkglib_LTLIBRARIES = libgom-1.0.la
 
+libgom_1_0_la_built_sources = \
+    gom-dbus.c \
+    gom-dbus.h \
+    $(NULL)
+
+nodist_libgom_1_0_la_SOURCES = \
+    $(libgom_1_0_la_built_sources)
+    $(NULL)
+
 libgom_1_0_la_SOURCES = \
+    gom-application.c \
+    gom-application.h \
     gom-miner.c \
     gom-miner.h \
     gom-tracker.c \
@@ -170,8 +181,25 @@ gom_zpj_miner_LDADD = \
     $(ZAPOJIT_LIBS) \
     $(NULL)
 
+BUILT_SOURCES = \
+    $(libgom_1_0_la_built_sources) \
+    $(NULL)
+
+CLEANFILES = \
+    $(BUILT_SOURCES) \
+    $(NULL)
+
 EXTRA_DIST = \
+    gom-dbus.xml \
     gom-miner-main.c \
     $(NULL)
 
+gom-dbus.h gom-dbus.c: gom-dbus.xml
+       $(AM_V_GEN)gdbus-codegen \
+               --c-namespace Gom \
+               --generate-c-code gom-dbus \
+               --interface-prefix org.gnome.OnlineMiners. \
+               --annotate "org.gnome.OnlineMiners.Miner" org.gtk.GDBus.C.Name DBus \
+               $<
+
 -include $(top_srcdir)/git.mk
diff --git a/src/gom-application.c b/src/gom-application.c
new file mode 100644
index 0000000..216202d
--- /dev/null
+++ b/src/gom-application.c
@@ -0,0 +1,242 @@
+/*
+ * GNOME Online Miners - crawls through your online content
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ *
+ */
+
+#include "config.h"
+
+#include "gom-application.h"
+#include "gom-dbus.h"
+#include "gom-miner.h"
+
+#define AUTOQUIT_TIMEOUT 5 /* seconds */
+
+struct _GomApplication
+{
+  GApplication parent;
+  GCancellable *cancellable;
+  GomDBus *skeleton;
+  GomMiner *miner;
+  GType miner_type;
+  gboolean refreshing;
+};
+
+struct _GomApplicationClass
+{
+  GApplicationClass parent_class;
+};
+
+enum
+{
+  PROP_0,
+  PROP_MINER_TYPE
+};
+
+G_DEFINE_TYPE (GomApplication, gom_application, G_TYPE_APPLICATION);
+
+static void
+gom_application_refresh_db_cb (GObject *source,
+                               GAsyncResult *res,
+                               gpointer user_data)
+{
+  GomApplication *self;
+  GDBusMethodInvocation *invocation = user_data;
+  GError *error = NULL;
+
+  self = GOM_APPLICATION (g_application_get_default ());
+  g_application_release (G_APPLICATION (self));
+  self->refreshing = FALSE;
+
+  gom_miner_refresh_db_finish (GOM_MINER (source), res, &error);
+  if (error != NULL)
+    {
+      g_printerr ("Failed to refresh the DB cache: %s\n", error->message);
+      g_dbus_method_invocation_take_error (invocation, error);
+      goto out;
+    }
+
+  gom_dbus_complete_refresh_db (self->skeleton, invocation);
+
+ out:
+  g_object_unref (invocation);
+}
+
+static gboolean
+gom_application_refresh_db (GomApplication *self,
+                            GDBusMethodInvocation *invocation)
+{
+  if (self->refreshing)
+    goto out;
+
+  g_application_hold (G_APPLICATION (self));
+
+  gom_miner_refresh_db_async (self->miner,
+                              self->cancellable,
+                              gom_application_refresh_db_cb,
+                              g_object_ref (invocation));
+
+ out:
+  return TRUE;
+}
+
+static gboolean
+gom_application_dbus_register (GApplication *application,
+                               GDBusConnection *connection,
+                               const gchar *object_path,
+                               GError **error)
+{
+  GomApplication *self = GOM_APPLICATION (application);
+  gboolean retval = FALSE;
+
+  if (!G_APPLICATION_CLASS (gom_application_parent_class)->dbus_register (application,
+                                                                          connection,
+                                                                          object_path,
+                                                                          error))
+    goto out;
+
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton),
+                                         connection,
+                                         object_path,
+                                         error))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  return retval;
+}
+
+static void
+gom_application_dbus_unregister (GApplication *application,
+                                 GDBusConnection *connection,
+                                 const gchar *object_path)
+{
+  GomApplication *self = GOM_APPLICATION (application);
+
+  if (self->skeleton != NULL)
+    {
+      if (g_dbus_interface_skeleton_has_connection (G_DBUS_INTERFACE_SKELETON (self->skeleton), connection))
+        g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (self->skeleton),
+                                                            connection);
+    }
+
+  G_APPLICATION_CLASS (gom_application_parent_class)->dbus_unregister (application, connection, object_path);
+}
+
+static void
+gom_application_shutdown (GApplication *application)
+{
+  GomApplication *self = GOM_APPLICATION (application);
+
+  g_cancellable_cancel (self->cancellable);
+
+  G_APPLICATION_CLASS (gom_application_parent_class)->shutdown (application);
+}
+
+static void
+gom_application_constructed (GObject *object)
+{
+  GomApplication *self = GOM_APPLICATION (object);
+  const gchar *display_name;
+
+  G_OBJECT_CLASS (gom_application_parent_class)->constructed (object);
+
+  self->miner = g_object_new (self->miner_type, NULL);
+  display_name = gom_miner_get_display_name (self->miner);
+  gom_dbus_set_display_name (self->skeleton, display_name);
+}
+
+static void
+gom_application_dispose (GObject *object)
+{
+  GomApplication *self = GOM_APPLICATION (object);
+
+  g_clear_object (&self->cancellable);
+  g_clear_object (&self->miner);
+  g_clear_object (&self->skeleton);
+
+  G_OBJECT_CLASS (gom_application_parent_class)->dispose (object);
+}
+
+static void
+gom_application_set_property (GObject *object,
+                              guint prop_id,
+                              const GValue *value,
+                              GParamSpec *pspec)
+{
+  GomApplication *self = GOM_APPLICATION (object);
+
+  switch (prop_id)
+    {
+    case PROP_MINER_TYPE:
+      self->miner_type = g_value_get_gtype (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gom_application_init (GomApplication *self)
+{
+  self->cancellable = g_cancellable_new ();
+
+  self->skeleton = gom_dbus_skeleton_new ();
+  g_signal_connect_swapped (self->skeleton, "handle-refresh-db", G_CALLBACK (gom_application_refresh_db), 
self);
+}
+
+static void
+gom_application_class_init (GomApplicationClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
+
+  oclass->constructed = gom_application_constructed;
+  oclass->dispose = gom_application_dispose;
+  oclass->set_property = gom_application_set_property;
+  application_class->dbus_register = gom_application_dbus_register;
+  application_class->dbus_unregister = gom_application_dbus_unregister;
+  application_class->shutdown = gom_application_shutdown;
+
+  g_object_class_install_property (oclass,
+                                   PROP_MINER_TYPE,
+                                   g_param_spec_gtype ("miner-type",
+                                                       "Miner type",
+                                                       "A GType representing the miner class",
+                                                       GOM_TYPE_MINER,
+                                                       G_PARAM_CONSTRUCT_ONLY
+                                                       | G_PARAM_STATIC_STRINGS
+                                                       | G_PARAM_WRITABLE));
+}
+
+GApplication *
+gom_application_new (const gchar *application_id,
+                     GType miner_type)
+{
+  return g_object_new (GOM_TYPE_APPLICATION,
+                       "application-id", application_id,
+                       "flags", G_APPLICATION_IS_SERVICE,
+                       "inactivity-timeout", AUTOQUIT_TIMEOUT,
+                       "miner-type", miner_type,
+                       NULL);
+}
diff --git a/src/gom-application.h b/src/gom-application.h
new file mode 100644
index 0000000..28771be
--- /dev/null
+++ b/src/gom-application.h
@@ -0,0 +1,62 @@
+/*
+ * GNOME Online Miners - crawls through your online content
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ *
+ */
+
+#ifndef __GOM_APPLICATION_H__
+#define __GOM_APPLICATION_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GOM_TYPE_APPLICATION (gom_application_get_type ())
+
+#define GOM_APPLICATION(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GOM_TYPE_APPLICATION, GomApplication))
+
+#define GOM_APPLICATION_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GOM_TYPE_APPLICATION, GomApplicationClass))
+
+#define GOM_IS_APPLICATION(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GOM_TYPE_APPLICATION))
+
+#define GOM_IS_APPLICATION_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GOM_TYPE_APPLICATION))
+
+#define GOM_APPLICATION_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GOM_TYPE_APPLICATION, GomApplicationClass))
+
+typedef struct _GomApplication      GomApplication;
+typedef struct _GomApplicationClass GomApplicationClass;
+
+GType gom_application_get_type (void);
+
+GApplication * gom_application_new (const gchar *application_id, GType miner_type);
+
+G_END_DECLS
+
+#endif /* __GOM_APPLICATION_H__ */
diff --git a/src/gom-dbus.xml b/src/gom-dbus.xml
new file mode 100644
index 0000000..683e31b
--- /dev/null
+++ b/src/gom-dbus.xml
@@ -0,0 +1,30 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+
+<!--
+ GNOME Online Miners - crawls through your online content
+ Copyright (c) 2014 Red Hat, Inc.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+-->
+
+<node>
+  <interface name='org.gnome.OnlineMiners.Miner'>
+    <method name='RefreshDB'>
+    </method>
+    <property name='DisplayName' type='s' access='read'/>
+  </interface>
+</node>
diff --git a/src/gom-miner-main.c b/src/gom-miner-main.c
index d8e7447..3f82659 100644
--- a/src/gom-miner-main.c
+++ b/src/gom-miner-main.c
@@ -30,219 +30,26 @@
 #include <glib-unix.h>
 #include <glib.h>
 
+#include "gom-application.h"
 #include "tracker-ioprio.h"
 #include "tracker-sched.h"
 
-#define AUTOQUIT_TIMEOUT 5 /* seconds */
-
-static const gchar introspection_xml[] =
-  "<node>"
-  "  <interface name='org.gnome.OnlineMiners.Miner'>"
-  "    <method name='RefreshDB'>"
-  "    </method>"
-  "    <property name='DisplayName' type='s' access='read'/>"
-  "  </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 GomMiner *miner = NULL;
-
-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);
+  GApplication *app = user_data;
 
+  g_application_quit (app);
   return FALSE;
 }
 
-static void
-miner_refresh_db_ready_cb (GObject *source,
-                           GAsyncResult *res,
-                           gpointer user_data)
-{
-  GDBusMethodInvocation *invocation = user_data;
-  GError *error = NULL;
-
-  gom_miner_refresh_db_finish (GOM_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);
-    }
-
-  g_object_unref (invocation);
-}
-
-static void
-handle_refresh_db (GDBusMethodInvocation *invocation)
-{
-  ensure_autoquit_off ();
-
-  /* if we're refreshing already, compress with the current request */
-  if (refreshing)
-    return;
-
-  refreshing = TRUE;
-  cancellable = g_cancellable_new ();
-
-  gom_miner_refresh_db_async (miner, cancellable,
-                              miner_refresh_db_ready_cb, g_object_ref (invocation));
-}
-
-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 (invocation);
-  else
-    g_assert_not_reached ();
-}
-
-static GVariant *
-handle_get_display_name ()
-{
-  return g_variant_new_string (gom_miner_get_display_name (miner));
-}
-
-static GVariant *
-handle_get_property (GDBusConnection       *connection,
-                     const gchar           *sender,
-                     const gchar           *object_path,
-                     const gchar           *interface_name,
-                     const gchar           *property_name,
-                     GError               **error,
-                     gpointer               user_data)
-{
-  if (g_strcmp0 (property_name, "DisplayName") == 0)
-    return handle_get_display_name ();
-
-  g_assert_not_reached ();
-
-  return NULL;
-}
-
-static const GDBusInterfaceVTable interface_vtable =
-{
-  handle_method_call,
-  handle_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);
-    }
-
-  miner = g_object_new (MINER_TYPE, NULL);
-  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)
 {
+  GApplication *app;
+  gint exit_status;
+
   tracker_sched_idle ();
   tracker_ioprio_init ();
 
@@ -255,34 +62,21 @@ main (int argc,
       g_warning ("Couldn't set nice value to 19, %s", (str != NULL) ? str : "no error given");
     }
 
-  ensure_autoquit_on ();
-  loop = g_main_loop_new (NULL, FALSE);
+  app = gom_application_new (MINER_BUS_NAME, MINER_TYPE);
+  if (g_getenv (MINER_NAME "_MINER_PERSIST") != NULL)
+    g_application_hold (app);
 
   g_unix_signal_add_full (G_PRIORITY_DEFAULT,
                          SIGTERM,
                          signal_handler_cb,
-                         loop, NULL);
+                         app, 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);
+                         app, NULL);
 
-  if (name_owner_id != 0)
-    g_bus_unown_name (name_owner_id);
+  exit_status = g_application_run (app, argc, argv);
+  g_object_unref (app);
 
-  return 0;
+  return exit_status;
 }


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