summaryrefslogtreecommitdiff
path: root/src/libtracker-sparql/tracker-backend.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtracker-sparql/tracker-backend.vala')
-rw-r--r--src/libtracker-sparql/tracker-backend.vala256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/libtracker-sparql/tracker-backend.vala b/src/libtracker-sparql/tracker-backend.vala
new file mode 100644
index 000000000..8c8e19edc
--- /dev/null
+++ b/src/libtracker-sparql/tracker-backend.vala
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+class Tracker.Sparql.Backend : Connection {
+ static bool initialized = false;
+ static Tracker.Sparql.Connection direct = null;
+ static Tracker.Sparql.Connection bus = null;
+ static enum Backend {
+ AUTO,
+ DIRECT,
+ BUS
+ }
+
+ private delegate Tracker.Sparql.Connection ModuleInitFunc ();
+
+ public Backend (bool direct_only = false) throws Sparql.Error
+ requires (!initialized) {
+ if (!Module.supported ()) {
+ return;
+ }
+
+ try {
+ load_plugins (direct_only);
+ } catch (GLib.Error e) {
+ throw new Sparql.Error.INTERNAL (e.message);
+ }
+
+ initialized = true;
+ }
+
+ public override Cursor query (string sparql, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null || direct != null) {
+ debug ("%s(): '%s'", Log.METHOD, sparql);
+ if (direct != null) {
+ return direct.query (sparql, cancellable);
+ } else {
+ return bus.query (sparql, cancellable);
+ }
+ }
+
+ public async override Cursor query_async (string sparql, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null || direct != null) {
+ debug ("%s(): '%s'", Log.METHOD, sparql);
+ if (direct != null) {
+ return yield direct.query_async (sparql, cancellable);
+ } else {
+ return yield bus.query_async (sparql, cancellable);
+ }
+ }
+
+ public override void update (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ debug ("%s(priority:%d): '%s'", Log.METHOD, priority, sparql);
+ bus.update (sparql, priority, cancellable);
+ }
+
+ public override GLib.Variant? update_blank (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ debug ("%s(priority:%d): '%s'", Log.METHOD, priority, sparql);
+ return bus.update_blank (sparql, priority, cancellable);
+ }
+
+ public async override void update_async (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ debug ("%s(priority:%d): '%s'", Log.METHOD, priority, sparql);
+ yield bus.update_async (sparql, priority, cancellable);
+ }
+
+ public async override GLib.Variant? update_blank_async (string sparql, int priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ debug ("%s(priority:%d): '%s'", Log.METHOD, priority, sparql);
+ return yield bus.update_blank_async (sparql, priority, cancellable);
+ }
+
+ public override void load (File file, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ var uri = file.get_uri ();
+ debug ("%s(): '%s'", Log.METHOD, uri);
+ bus.load (file, cancellable);
+ }
+
+ public async override void load_async (File file, Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ var uri = file.get_uri ();
+ debug ("%s(): '%s'", Log.METHOD, uri);
+ yield bus.load_async (file, cancellable);
+ }
+
+ public override Cursor? statistics (Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ debug ("%s()", Log.METHOD);
+ return bus.statistics (cancellable);
+ }
+
+ public async override Cursor? statistics_async (Cancellable? cancellable = null) throws Sparql.Error, IOError
+ requires (bus != null) {
+ debug ("%s()", Log.METHOD);
+ return yield bus.statistics_async (cancellable);
+ }
+
+ // Plugin loading functions
+ private bool load_plugins (bool direct_only) throws GLib.Error {
+ string env_path = Environment.get_variable ("TRACKER_SPARQL_MODULE_PATH");
+ string path;
+
+ if (env_path != null && env_path.length > 0) {
+ path = env_path;
+ } else {
+ path = Config.SPARQL_MODULES_DIR;
+ }
+
+ File dir = File.new_for_path (path);
+ string dir_path = dir.get_path ();
+
+ string env_backend = Environment.get_variable ("TRACKER_SPARQL_BACKEND");
+ Backend backend = Backend.AUTO;
+
+ if (env_backend != null) {
+ if (env_backend.ascii_casecmp ("direct") == 0) {
+ backend = Backend.DIRECT;
+ debug ("Using backend = 'DIRECT'");
+ } else if (env_backend.ascii_casecmp ("bus") == 0) {
+ backend = Backend.BUS;
+ debug ("Using backend = 'BUS'");
+ } else {
+ warning ("Environment variable TRACKER_SPARQL_BACKEND set to unknown value '%s'", env_backend);
+ }
+ }
+
+ if (backend == Backend.AUTO) {
+ if (direct_only && backend == Backend.AUTO) {
+ backend = Backend.DIRECT;
+ debug ("Using backend = 'DIRECT'");
+ } else {
+ debug ("Using backend = 'AUTO'");
+ }
+ }
+
+ if (direct_only && backend == Backend.BUS) {
+ debug ("Backend set in environment contradicts requested connection type, using environment to override");
+ }
+
+ debug ("Searching for modules in folder '%s' ..", dir_path);
+
+ Tracker.Sparql.Connection connection;
+
+ switch (backend) {
+ case backend.AUTO:
+ string direct_path = Module.build_path (dir_path, "tracker-direct");
+ direct = load_plugins_from_path (direct_path, false /* required */);
+
+ string bus_path = Module.build_path (dir_path, "tracker-bus");
+ bus = load_plugins_from_path (bus_path, true /* required */);
+
+ connection = bus;
+ break;
+
+ case backend.DIRECT:
+ string direct_path = Module.build_path (dir_path, "tracker-direct");
+ connection = direct = load_plugins_from_path (direct_path, true /* required */);
+ break;
+
+ case backend.BUS:
+ string bus_path = Module.build_path (dir_path, "tracker-bus");
+ connection = bus = load_plugins_from_path (bus_path, true /* required */);
+ break;
+
+ default:
+ assert_not_reached ();
+ }
+
+ debug ("Finished searching for modules");
+
+ return connection != null;
+ }
+
+ private Tracker.Sparql.Connection? load_plugins_from_path (string path, bool required) throws GLib.Error {
+ try {
+ File file = File.new_for_path (path);
+ assert (file != null);
+
+ FileInfo info = null;
+
+ string attributes = FILE_ATTRIBUTE_STANDARD_NAME + "," +
+ FILE_ATTRIBUTE_STANDARD_TYPE + "," +
+ FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE;
+
+ info = file.query_info (attributes,
+ FileQueryInfoFlags.NONE,
+ null);
+
+ string content_type = info.get_content_type ();
+ string mime = g_content_type_get_mime_type (content_type);
+ string expected_mime = "application/x-sharedlib";
+
+ if (mime != expected_mime) {
+ throw new IOError.FAILED ("Could not load plugin, mime type was '%s', expected:'%s'",
+ mime,
+ expected_mime);
+ }
+
+ Module module = Module.open (path, ModuleFlags.BIND_LOCAL);
+ if (module == null) {
+ throw new IOError.FAILED ("Failed to load module from path '%s': %s",
+ path,
+ Module.error ());
+ }
+
+ void *function;
+
+ if (!module.symbol ("module_init", out function)) {
+ throw new IOError.FAILED ("Failed to find entry point function '%s' in '%s': %s",
+ "module_init",
+ path,
+ Module.error ());
+ }
+
+ ModuleInitFunc module_init = (ModuleInitFunc) function;
+ assert (module_init != null);
+
+ // We don't want our modules to ever unload
+ module.make_resident ();
+
+ // Call module init function
+ Tracker.Sparql.Connection c = module_init ();
+
+ debug ("Loaded module source: '%s'", module.name ());
+
+ return c;
+ } catch (GLib.Error e) {
+ if (required) {
+ // plugin required => error is fatal
+ throw e;
+ } else {
+ return null;
+ }
+ }
+ }
+}
+