[tracker/wip/carlosg/tracker-3.0-api-breaks: 62/63] tracker: Add "endpoint" CLI subcommand



commit f45bd2728c33d64e521e856ff3c96c3636ae882f
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jan 15 20:15:25 2020 +0100

    tracker: Add "endpoint" CLI subcommand
    
    This command allows to create arbitrary endpoints, just a database
    path, ontology, and service name are required.

 docs/manpages/meson.build        |   1 +
 docs/manpages/tracker-endpoint.1 |  72 ++++++++++++
 src/tracker/meson.build          |   1 +
 src/tracker/tracker-endpoint.c   | 244 +++++++++++++++++++++++++++++++++++++++
 src/tracker/tracker-endpoint.h   |  27 +++++
 src/tracker/tracker-main.c       |   4 +-
 6 files changed, 348 insertions(+), 1 deletion(-)
---
diff --git a/docs/manpages/meson.build b/docs/manpages/meson.build
index af345d492..cd60b2dbe 100644
--- a/docs/manpages/meson.build
+++ b/docs/manpages/meson.build
@@ -1,3 +1,4 @@
+install_man('tracker-endpoint.1')
 install_man('tracker-info.1')
 install_man('tracker-sparql.1')
 install_man('tracker-sql.1')
diff --git a/docs/manpages/tracker-endpoint.1 b/docs/manpages/tracker-endpoint.1
new file mode 100644
index 000000000..cb6009db9
--- /dev/null
+++ b/docs/manpages/tracker-endpoint.1
@@ -0,0 +1,72 @@
+.TH tracker-endpoint 1 "January 2020" GNU "User Commands"
+
+.SH NAME
+tracker-endpoint \- Create a SPARQL endpoint
+
+.SH SYNOPSIS
+.nf
+\fBtracker endpoint\fR [\-\-dbus\-service | \-s] <\fIservice_name\fR>
+                 [\-\-database\-path | \-d] <\fIdatabase_path\fR>
+                 [[\-\-ontology | \-o] <\fIontology_name\fR> |
+                  [\-\-ontology\-path | \-p] <\fIontology_path\fR>]
+                 [[\-\-system | \-\-session]]
+.fi
+
+.SH DESCRIPTION
+This command allows creating SPARQL endpoints. The endpoint will be
+able to handle SPARQL select and update queries, and notify about changes
+in it.
+
+The endpoint is exported via DBus, accessible through the given \fIservice_name\fR, either using it in a 
\fBSERVICE\fR clause, or by creating a dedicated
+bus-based SPARQL connection.
+
+When creating a database, the \fIontology_name\fR (or alternatively, a \fIontology_path\fR) must be provided 
in order to generate the database. If \fIontology_name\fR is used, the ontology must exist in 
\fI$datadir/tracker/ontologies\fR
+
+The database itself will be stored according to \fIdatabase_path\fR.
+
+.SH OPTIONS
+.TP
+.B \-s, \-\-dbus\-service\fR=<\fIservice_name\fR>
+Service name to use on the endpoint.
+.TP
+.B \-d, \-\-database\-path\fR=<\fIdatabase_path\fR>
+The path where the database will be stored.
+.TP
+.B \-o, \-\-ontology
+The name of an ontology in \fI$datadir/tracker/ontologies\fR to use on the
+constructed database.
+.TP
+.B \-p, \-\-ontology\-path
+Full path to an ontology to use on the constructed database.
+.TP
+.B \-\-session
+Use the session bus. This is the default.
+.TP
+.B \-\-system
+Use the system bus.
+
+.SH EXAMPLES
+.TP
+Export a Nepomuk endpoint with the \fIorg.example.Example1\fR bus name.
+
+.BR
+.nf
+$ tracker endpoint -s org.example.Example1 -o nepomuk -d /tmp/example1
+.fi
+
+.TP
+Access this endpoint with the \fBtracker-sparql(1)\fR subcommand.
+
+.BR
+.nf
+$ tracker sparql --dbus-service org.example.Example1 -q "
+  SELECT ?s ?o
+  WHERE {
+    ?u a ?o
+  }"
+.fi
+
+.SH SEE ALSO
+.BR tracker-sparql (1),
+.TP
+.BR https://www.w3.org/TR/sparql11-query/
diff --git a/src/tracker/meson.build b/src/tracker/meson.build
index 530166114..7b7161c05 100644
--- a/src/tracker/meson.build
+++ b/src/tracker/meson.build
@@ -1,4 +1,5 @@
 modules = [
+    'endpoint',
     'help',
     'info',
     'sparql',
diff --git a/src/tracker/tracker-endpoint.c b/src/tracker/tracker-endpoint.c
new file mode 100644
index 000000000..0a0b6dea8
--- /dev/null
+++ b/src/tracker/tracker-endpoint.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <glib-unix.h>
+#include <glib/gi18n.h>
+
+#include <libtracker-sparql/tracker-sparql.h>
+
+#include "tracker-endpoint.h"
+
+static gchar *database_path = NULL;
+static gchar *dbus_service = NULL;
+static gchar *ontology_name = NULL;
+static gchar *ontology_path = NULL;
+static gboolean session_bus = FALSE;
+static gboolean system_bus = FALSE;
+static gboolean name_owned = FALSE;
+
+static GOptionEntry entries[] = {
+       { "database", 'd', 0, G_OPTION_ARG_FILENAME, &database_path,
+         N_("Location of the database"),
+         N_("DIR")
+       },
+       { "dbus-service", 's', 0, G_OPTION_ARG_STRING, &dbus_service,
+         N_("Specify the DBus name of this endpoint"),
+         N_("NAME")
+       },
+       { "ontology", 'o', 0, G_OPTION_ARG_STRING, &ontology_name,
+         N_("Specify the ontology name used in this endpoint"),
+         N_("NAME")
+       },
+       { "ontology-path", 'p', 0, G_OPTION_ARG_FILENAME, &ontology_path,
+         N_("Specify a path to an ontology to be used in this endpoint"),
+         N_("DIR")
+       },
+       { "session", 0, 0, G_OPTION_ARG_NONE, &session_bus,
+         N_("Use session bus"),
+         NULL
+       },
+       { "system", 0, 0, G_OPTION_ARG_NONE, &system_bus,
+         N_("Use system bus"),
+         NULL
+       },
+       { NULL }
+};
+
+static gboolean
+sanity_check (void)
+{
+       if (!database_path) {
+               g_print ("%s\n", _("No database path was provided"));
+               return FALSE;
+       }
+
+       if (!dbus_service) {
+               g_print ("%s\n", _("No endpoint information was provided"));
+               return FALSE;
+       }
+
+       if (!!ontology_path == !!ontology_name) {
+               g_print ("%s\n", _("One “ontology” or “ontology path” option should be provided"));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static gboolean
+sigterm_cb (gpointer user_data)
+{
+       g_main_loop_quit (user_data);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void
+name_acquired_cb (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+       name_owned = TRUE;
+       g_main_loop_quit (user_data);
+}
+
+static void
+name_lost_cb (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+       name_owned = FALSE;
+       g_main_loop_quit (user_data);
+}
+
+int
+tracker_endpoint (int argc, const char **argv)
+{
+       TrackerSparqlConnection *connection;
+       TrackerEndpoint *endpoint = NULL;
+       GDBusConnection *dbus_connection;
+       GMainLoop *main_loop;
+       GOptionContext *context;
+       GError *error = NULL;
+       GFile *database, *ontology = NULL;
+
+       context = g_option_context_new (NULL);
+       g_option_context_add_main_entries (context, entries, NULL);
+
+       argv[0] = "tracker endpoint";
+
+       if (!g_option_context_parse (context, &argc, (char***) &argv, &error)) {
+               g_printerr ("%s, %s\n", _("Unrecognized options"), error->message);
+               g_error_free (error);
+               g_option_context_free (context);
+               return EXIT_FAILURE;
+       }
+
+       if (!sanity_check ()) {
+               gchar *help;
+
+               help = g_option_context_get_help (context, TRUE, NULL);
+               g_printerr ("%s\n", help);
+               g_free (help);
+               g_option_context_free (context);
+               return EXIT_FAILURE;
+       }
+
+       database = g_file_new_for_commandline_arg (database_path);
+       if (ontology_path) {
+               ontology = g_file_new_for_commandline_arg (ontology_path);
+       } else if (ontology_name) {
+               gchar *path = g_build_filename (SHAREDIR, "tracker", "ontologies", ontology_name, NULL);
+               ontology = g_file_new_for_path (path);
+               g_free (path);
+       }
+
+       g_assert (ontology != NULL);
+       g_print (_("Opening database at %s…"), database_path);
+       g_print ("\n");
+
+       connection = tracker_sparql_connection_new (0, database, ontology, NULL, &error);
+       if (!connection) {
+               g_printerr ("%s\n", error->message);
+               g_error_free (error);
+               g_option_context_free (context);
+               return EXIT_FAILURE;
+       }
+
+       g_print (_("Creating endpoint at %s…"), dbus_service);
+       g_print ("\n");
+
+       if (system_bus) {
+               dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+       } else {
+               dbus_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+       }
+
+       if (dbus_connection) {
+               endpoint = TRACKER_ENDPOINT (tracker_endpoint_dbus_new (connection,
+                                                                       dbus_connection,
+                                                                       NULL, NULL, &error));
+       }
+
+       main_loop = g_main_loop_new (NULL, FALSE);
+
+       if (endpoint) {
+               g_bus_own_name_on_connection (dbus_connection,
+                                             dbus_service,
+                                             G_BUS_NAME_OWNER_FLAGS_NONE,
+                                             name_acquired_cb,
+                                             name_lost_cb,
+                                             main_loop, NULL);
+
+               g_main_loop_run (main_loop);
+       }
+
+       if (error) {
+               g_printerr ("%s\n", error->message);
+               g_error_free (error);
+               g_option_context_free (context);
+               g_main_loop_unref (main_loop);
+               return EXIT_FAILURE;
+       }
+
+       if (!name_owned) {
+               g_printerr ("%s\n", _("Could not own DBus name"));
+               g_option_context_free (context);
+               g_main_loop_unref (main_loop);
+               return EXIT_FAILURE;
+       }
+
+       g_print ("%s\n", _("Listening to SPARQL commands. Press Ctrl-C to stop."));
+
+       g_unix_signal_add (SIGINT, sigterm_cb, main_loop);
+       g_unix_signal_add (SIGTERM, sigterm_cb, main_loop);
+
+       g_main_loop_run (main_loop);
+
+       if (!name_owned) {
+               g_printerr ("%s\n", _("DBus name lost"));
+               g_option_context_free (context);
+               g_main_loop_unref (main_loop);
+               return EXIT_FAILURE;
+       }
+
+       /* Carriage return, so we paper over the ^C */
+       g_print ("\r%s\n", _("Closing connection…"));
+       g_clear_object (&endpoint);
+
+       if (connection) {
+               tracker_sparql_connection_close (connection);
+               g_clear_object (&connection);
+       }
+
+       g_option_context_free (context);
+       g_main_loop_unref (main_loop);
+
+       return EXIT_SUCCESS;
+}
diff --git a/src/tracker/tracker-endpoint.h b/src/tracker/tracker-endpoint.h
new file mode 100644
index 000000000..b7b86e2ea
--- /dev/null
+++ b/src/tracker/tracker-endpoint.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __TRACKER_ENDPOINT_H__
+#define __TRACKER_ENDPOINT_H__
+
+int tracker_endpoint (int argc, const char **argv);
+
+#endif /* __TRACKER_ENDPOINT_H__ */
diff --git a/src/tracker/tracker-main.c b/src/tracker/tracker-main.c
index 4ac027ba9..5b8866d3a 100644
--- a/src/tracker/tracker-main.c
+++ b/src/tracker/tracker-main.c
@@ -28,6 +28,7 @@
 
 #include <libtracker-common/tracker-common.h>
 
+#include "tracker-endpoint.h"
 #include "tracker-help.h"
 #include "tracker-info.h"
 #include "tracker-sparql.h"
@@ -36,7 +37,7 @@
 const char usage_string[] =
        "tracker [--version] [--help]\n"
        "               <command> [<args>]";
- 
+
 const char usage_more_info_string[] =
        N_("See “tracker help <command>” to read about a specific subcommand.");
 
@@ -90,6 +91,7 @@ static struct cmd_struct commands[] = {
        { "help", tracker_help, NEED_NOTHING, N_("Get help on how to use Tracker and any of these commands") 
},
        { "info", tracker_info, NEED_WORK_TREE, N_("Show information known about local files or items 
indexed") },
        { "sparql", tracker_sparql, NEED_WORK_TREE, N_("Query and update the index using SPARQL or search, 
list and tree the ontology") },
+       { "endpoint", tracker_endpoint, NEED_NOTHING, N_("Create a SPARQL endpoint") },
        { "sql", tracker_sql, NEED_WORK_TREE, N_("Query the database at the lowest level using SQL") },
 };
 


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