[tracker/gdbus-server-wip] WIP
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/gdbus-server-wip] WIP
- Date: Tue, 4 Jan 2011 13:58:04 +0000 (UTC)
commit 956b8a3aba993150e0f06825e42af325494f7f9a
Author: Jürg Billeter <j bitron ch>
Date: Tue Dec 28 08:42:03 2010 +0100
WIP
configure.ac | 4 +-
src/libtracker-common/libtracker-common.vapi | 6 +
src/libtracker-common/tracker-common.h | 5 +-
src/libtracker-data/libtracker-data.vapi | 4 +
src/tracker-store/Makefile.am | 80 +--
src/tracker-store/tracker-backup.c | 229 ------
src/tracker-store/tracker-backup.h | 64 --
src/tracker-store/tracker-backup.vala | 192 +++++
src/tracker-store/tracker-dbus.c | 382 ----------
src/tracker-store/tracker-dbus.h | 42 --
src/tracker-store/tracker-dbus.vala | 344 +++++++++
src/tracker-store/tracker-events.c | 4 +
src/tracker-store/tracker-locale-change.c | 4 +
src/tracker-store/tracker-main.c | 575 ---------------
src/tracker-store/tracker-main.vala | 493 +++++++++++++
src/tracker-store/tracker-marshal.list | 12 -
src/tracker-store/tracker-resources.c | 804 ---------------------
src/tracker-store/tracker-resources.h | 95 ---
src/tracker-store/tracker-resources.vala | 778 ++++++++++++++++++++
src/tracker-store/tracker-statistics.c | 116 ---
src/tracker-store/tracker-statistics.h | 58 --
src/tracker-store/tracker-statistics.vala | 87 +++
src/tracker-store/tracker-status.c | 231 ------
src/tracker-store/tracker-status.h | 77 --
src/tracker-store/tracker-status.vala | 139 ++++
src/tracker-store/tracker-steroids.c | 997 --------------------------
src/tracker-store/tracker-steroids.h | 57 --
src/tracker-store/tracker-steroids.vala | 862 ++++++++++++++++++++++
src/tracker-store/tracker-store.c | 733 -------------------
src/tracker-store/tracker-store.h | 92 ---
src/tracker-store/tracker-store.vala | 641 +++++++++++++++++
src/tracker-store/tracker-writeback.c | 4 +
32 files changed, 3589 insertions(+), 4622 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index e73bcd2..3ea136c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,7 @@ AC_INIT([tracker],
[tracker],
[http://www.tracker-project.org])
-AC_CONFIG_SRCDIR([src/tracker-store/tracker-main.c])
+AC_CONFIG_SRCDIR([src/tracker-store/tracker-main.vala])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -311,8 +311,6 @@ TRACKER_STORE_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
gio-unix-2.0 >= $GLIB_REQUIRED
gthread-2.0 >= $GLIB_REQUIRED
gmodule-2.0 >= $GLIB_REQUIRED
- dbus-1 >= $DBUS_REQUIRED
- dbus-glib-1 >= $DBUS_GLIB_REQUIRED
sqlite3 >= $SQLITE_REQUIRED"
PKG_CHECK_MODULES(TRACKER_STORE, [$TRACKER_STORE_REQUIRED])
diff --git a/src/libtracker-common/libtracker-common.vapi b/src/libtracker-common/libtracker-common.vapi
index eb546db..511ae77 100644
--- a/src/libtracker-common/libtracker-common.vapi
+++ b/src/libtracker-common/libtracker-common.vapi
@@ -58,5 +58,11 @@ namespace Tracker {
public static void save_string_list (void *object, string property, GLib.KeyFile key_file, string group, string key);
public static void save_directory_list (void *object, string property, GLib.KeyFile key_file, string group, string key);
}
+
+ [CCode (cheader_filename = "libtracker-common/tracker-common.h")]
+ namespace Log {
+ public bool init (int verbosity, out string used_filename);
+ public void shutdown ();
+ }
}
diff --git a/src/libtracker-common/tracker-common.h b/src/libtracker-common/tracker-common.h
index 7fcfc72..ac2c876 100644
--- a/src/libtracker-common/tracker-common.h
+++ b/src/libtracker-common/tracker-common.h
@@ -30,7 +30,6 @@
#include "tracker-config-file.h"
#include "tracker-date-time.h"
-#include "tracker-dbus.h"
#include "tracker-file-utils.h"
#include "tracker-ioprio.h"
#include "tracker-keyfile-object.h"
@@ -43,6 +42,10 @@
#include "tracker-utils.h"
#include "tracker-locale.h"
+#if !defined (TRACKER_STORE_COMPILATION)
+#include "tracker-dbus.h"
+#endif
+
#undef __LIBTRACKER_COMMON_INSIDE__
#endif /* __LIBTRACKER_COMMON_H__ */
diff --git a/src/libtracker-data/libtracker-data.vapi b/src/libtracker-data/libtracker-data.vapi
index 27955a0..859fb1a 100644
--- a/src/libtracker-data/libtracker-data.vapi
+++ b/src/libtracker-data/libtracker-data.vapi
@@ -137,11 +137,15 @@ namespace Tracker {
[CCode (cheader_filename = "libtracker-data/tracker-data-query.h,libtracker-data/tracker-data-update.h")]
namespace Data {
public int query_resource_id (string uri);
+ public DBCursor query_sparql_cursor (string query) throws Sparql.Error;
public void begin_db_transaction ();
public void commit_db_transaction ();
public void begin_transaction () throws DBInterfaceError;
public void commit_transaction () throws DBInterfaceError;
public void rollback_transaction ();
+ public void update_sparql (string update) throws Sparql.Error;
+ public GLib.PtrArray update_sparql_blank (string update) throws Sparql.Error;
+ public void notify_transaction (bool start_timer);
public void delete_statement (string graph, string subject, string predicate, string object) throws Sparql.Error, DateError;
public void insert_statement (string graph, string subject, string predicate, string object) throws Sparql.Error, DateError;
public void insert_statement_with_uri (string graph, string subject, string predicate, string object) throws Sparql.Error;
diff --git a/src/tracker-store/Makefile.am b/src/tracker-store/Makefile.am
index b113296..fde7871 100644
--- a/src/tracker-store/Makefile.am
+++ b/src/tracker-store/Makefile.am
@@ -8,7 +8,9 @@ AM_CPPFLAGS = \
-DPUSH_MODULES_DIR=\""$(libdir)/tracker-$(TRACKER_API_VERSION)/push-modules/daemon"\" \
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
- $(TRACKER_STORE_CFLAGS)
+ $(TRACKER_STORE_CFLAGS) \
+ -DTRACKER_STORE_COMPILATION \
+ -DGETTEXT_PACKAGE=\"NULL\"
#
# Daemon sources
@@ -16,31 +18,33 @@ AM_CPPFLAGS = \
libexec_PROGRAMS = tracker-store
tracker_store_SOURCES = \
- $(marshal_sources) \
- $(dbus_sources) \
- tracker-backup.c \
- tracker-backup.h \
+ tracker-backup.vala \
tracker-config.c \
- tracker-config.h \
- tracker-dbus.c \
- tracker-dbus.h \
+ tracker-dbus.vala \
tracker-events.c \
+ tracker-locale-change.c \
+ tracker-main.vala \
+ tracker-resources.vala \
+ tracker-statistics.vala \
+ tracker-status.vala \
+ tracker-steroids.vala \
+ tracker-store.vala \
+ tracker-writeback.c
+
+noinst_HEADERS = \
+ tracker-config.h \
tracker-events.h \
- tracker-writeback.c \
- tracker-writeback.h \
- tracker-main.c \
- tracker-resources.c \
- tracker-resources.h \
- tracker-statistics.c \
- tracker-statistics.h \
- tracker-store.c \
- tracker-store.h \
- tracker-status.c \
- tracker-status.h \
- tracker-steroids.c \
- tracker-steroids.h \
tracker-locale-change.h \
- tracker-locale-change.c
+ tracker-writeback.h
+
+tracker_store_VALAFLAGS = \
+ --pkg gio-2.0 \
+ --pkg gio-unix-2.0 \
+ $(BUILD_VALAFLAGS) \
+ $(top_srcdir)/src/libtracker-common/libtracker-common.vapi \
+ $(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi \
+ $(top_srcdir)/src/libtracker-data/tracker-sparql-query.vapi \
+ $(top_srcdir)/src/libtracker-data/libtracker-data.vapi
tracker_store_LDADD = \
$(top_builddir)/src/libtracker-data/libtracker-data.la \
@@ -48,35 +52,3 @@ tracker_store_LDADD = \
$(top_builddir)/src/libtracker-sparql/libtracker-sparql- TRACKER_API_VERSION@.la \
$(BUILD_LIBS) \
$(TRACKER_STORE_LIBS)
-
-marshal_sources = \
- tracker-marshal.h \
- tracker-marshal.c
-
-dbus_sources = \
- tracker-backup-glue.h \
- tracker-resources-glue.h \
- tracker-statistics-glue.h \
- tracker-status-glue.h
-
-tracker-marshal.h: tracker-marshal.list
- $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --prefix=tracker_marshal --header > $@
-
-tracker-marshal.c: tracker-marshal.list
- $(AM_V_GEN)echo "#include \"tracker-marshal.h\"" > $@ && \
- $(GLIB_GENMARSHAL) $< --prefix=tracker_marshal --body >> $@
-
-%-glue.h: $(top_srcdir)/data/dbus/%.xml
- $(AM_V_GEN)$(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
-
-%-client.h: $(top_srcdir)/data/dbus/%.xml
- $(AM_V_GEN)$(DBUSBINDINGTOOL) --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^
-
-BUILT_SOURCES = \
- $(marshal_sources) \
- $(dbus_sources)
-
-CLEANFILES = $(BUILT_SOURCES)
-
-EXTRA_DIST = tracker-marshal.list
-
diff --git a/src/tracker-store/tracker-backup.vala b/src/tracker-store/tracker-backup.vala
new file mode 100644
index 0000000..2d69192
--- /dev/null
+++ b/src/tracker-store/tracker-backup.vala
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2006, Jamie McCracken <jamiemcc gnome org>
+ * Copyright (C) 2008, Nokia <ivan frade nokia com>
+ *
+ * This library 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 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 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.
+ */
+
+#if 0
+
+struct TrackerDBusMethodInfo {
+ DBusGMethodInvocation *context;
+ guint request_id;
+ gchar *journal_uri;
+ TrackerResources *resources;
+ TrackerNotifyClassGetter getter;
+ GFile *destination;
+}
+
+[DBus (name = "org.freedesktop.Tracker1.Backup")]
+class Tracker.Backup {
+ static void
+ backup_callback (GError *error, gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &error,
+ NULL);
+ dbus_g_method_return_error (info->context, error);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id,
+ info->context);
+
+ dbus_g_method_return (info->context);
+
+ if (info->resources) {
+ tracker_events_init (info->getter);
+ tracker_resources_enable_signals (info->resources);
+ g_object_unref (info->resources);
+ }
+
+ tracker_store_set_active (TRUE, NULL, NULL);
+ }
+
+ static void
+ restore_callback (GError *error, gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &error,
+ NULL);
+ dbus_g_method_return_error (info->context, error);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id,
+ info->context);
+
+ dbus_g_method_return (info->context);
+
+ if (info->resources) {
+ tracker_events_init (info->getter);
+ tracker_resources_enable_signals (info->resources);
+ g_object_unref (info->resources);
+ }
+
+ tracker_store_set_active (TRUE, NULL, NULL);
+ }
+
+
+ static void
+ backup_idle_set_active_false_cb (gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+
+ tracker_data_backup_save (info->destination,
+ backup_callback,
+ info,
+ (GDestroyNotify) g_free);
+
+ g_object_unref (info->destination);
+ }
+
+ public void save (string destination_uri) throws Error {
+ guint request_id;
+ TrackerDBusMethodInfo *info;
+ gpointer resources;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "D-Bus request to save backup into '%s'",
+ destination_uri);
+
+ info = g_new0 (TrackerDBusMethodInfo, 1);
+
+ info->request_id = request_id;
+ info->context = context;
+ info->destination = g_file_new_for_uri (destination_uri);
+
+ resources = tracker_dbus_get_object (TRACKER_TYPE_RESOURCES);
+
+ if (resources) {
+ info->resources = g_object_ref (resources);
+ tracker_resources_disable_signals (info->resources);
+ info->getter = tracker_events_get_class_getter ();
+ tracker_events_shutdown ();
+ }
+
+ tracker_store_set_active (FALSE, backup_idle_set_active_false_cb, info);
+ }
+
+ static void
+ restore_idle_set_active_false_cb (gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+ GFile *journal;
+ TrackerStatus *notifier;
+ TrackerBusyCallback busy_callback;
+ gpointer busy_user_data;
+
+ journal = g_file_new_for_uri (info->journal_uri);
+
+ notifier = TRACKER_STATUS (tracker_dbus_get_object (TRACKER_TYPE_STATUS));
+
+ busy_callback = tracker_status_get_callback (notifier,
+ &busy_user_data);
+
+ g_free (info->journal_uri);
+
+ tracker_data_backup_restore (journal,
+ restore_callback,
+ info,
+ (GDestroyNotify) g_free,
+ NULL,
+ busy_callback,
+ busy_user_data);
+
+ g_object_unref (journal);
+ }
+
+ public void restore (string journal_uri) throws Error {
+ guint request_id;
+ TrackerDBusMethodInfo *info;
+ gpointer resources;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "D-Bus request to restore backup from '%s'",
+ journal_uri);
+
+ info = g_new0 (TrackerDBusMethodInfo, 1);
+ info->request_id = request_id;
+ info->context = context;
+ info->journal_uri = g_strdup (journal_uri);
+ resources = tracker_dbus_get_object (TRACKER_TYPE_RESOURCES);
+
+ if (resources) {
+ info->resources = g_object_ref (resources);
+ tracker_resources_disable_signals (info->resources);
+ info->getter = tracker_events_get_class_getter ();
+ tracker_events_shutdown ();
+ }
+
+ tracker_store_set_active (FALSE, restore_idle_set_active_false_cb, info);
+ }
+}
+
+#endif
diff --git a/src/tracker-store/tracker-dbus.vala b/src/tracker-store/tracker-dbus.vala
new file mode 100644
index 0000000..c8417f4
--- /dev/null
+++ b/src/tracker-store/tracker-dbus.vala
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2006, Jamie McCracken <jamiemcc gnome org>
+ * Copyright (C) 2008, Nokia <ivan frade nokia com>
+ *
+ * This library 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 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 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.DBus {
+ static DBusConnection connection;
+
+ const string SERVICE = "org.freedesktop.Tracker1";
+
+#if 0
+ static DBusGProxy *gproxy;
+ static GSList *objects;
+#endif
+ static Tracker.Status notifier;
+#if 0
+ static TrackerBackup *backup;
+ static TrackerSteroids *steroids;
+
+ static gboolean
+ dbus_register_service (DBusGProxy *proxy,
+ const gchar *name)
+ {
+ GError *error = NULL;
+ guint result;
+
+ g_message ("Registering D-Bus service...\n"
+ " Name:'%s'",
+ name);
+
+ if (!org_freedesktop_DBus_request_name (proxy,
+ name,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ &result, &error)) {
+ g_critical ("Could not aquire name:'%s', %s",
+ name,
+ error ? error->message : "no error given");
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ g_critical ("D-Bus service name:'%s' is already taken, "
+ "perhaps the daemon is already running?",
+ name);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+#endif
+
+ static void register_object<T> (DBusConnection lconnection, T object, string path) {
+ message ("Registering D-Bus object...");
+ message (" Path:'%s'", path);
+ message (" Type:'%s'", typeof (T).name ());
+
+ lconnection.register_object (path, object);
+ }
+
+ public static bool register_names () {
+ /* Register the service name for org.freedesktop.Tracker */
+ Bus.own_name_on_connection (connection, SERVICE, (BusNameOwnerFlags) 1 << 2 /* DBUS_NAME_FLAG_DO_NOT_QUEUE */,
+ () => { /* name acquired */ },
+ () => { /* name lost, TODO: shutdown */ });
+
+ return true;
+ }
+
+ public static bool init () {
+#if 0
+ GError *error = NULL;
+
+ /* Don't reinitialize */
+ if (objects) {
+ return TRUE;
+ }
+#endif
+
+ if (connection != null) {
+ critical ("The DBus connection is already set, have we already initialized?");
+ return false;
+ }
+
+#if 0
+ if (gproxy) {
+ g_critical ("The DBusGProxy is already set, have we already initialized?");
+ return FALSE;
+ }
+#endif
+
+ try {
+ connection = Bus.get_sync (BusType.SESSION);
+ } catch (Error e) {
+ critical ("Could not connect to the D-Bus session bus, %s", e.message);
+ return false;
+ }
+
+#if 0
+ /* The definitions below (DBUS_SERVICE_DBUS, etc) are
+ * predefined for us to just use (dbus_g_proxy_...)
+ */
+ gproxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ dbus_g_proxy_add_signal (gproxy, "NameOwnerChanged",
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+#endif
+
+ return true;
+ }
+
+#if 0
+ static void
+ name_owner_changed_cb (DBusGProxy *proxy,
+ gchar *name,
+ gchar *old_owner,
+ gchar *new_owner,
+ gpointer user_data)
+ {
+ if (tracker_is_empty_string (new_owner) && !tracker_is_empty_string (old_owner)) {
+ /* This means that old_owner got removed */
+ tracker_resources_unreg_batches (user_data, old_owner);
+ }
+ }
+
+ static void
+ name_owner_changed_closure (gpointer data,
+ GClosure *closure)
+ {
+ }
+
+ static void
+ dbus_set_available (gboolean available)
+ {
+ if (available) {
+ if (!objects) {
+ tracker_dbus_register_objects ();
+ }
+ } else {
+ GSList *l;
+
+ if (objects) {
+ dbus_g_proxy_disconnect_signal (gproxy,
+ "NameOwnerChanged",
+ G_CALLBACK (name_owner_changed_cb),
+ tracker_dbus_get_object (TRACKER_TYPE_RESOURCES));
+ }
+
+
+ for (l = objects; l; l = l->next) {
+ dbus_g_connection_unregister_g_object (connection, l->data);
+ g_object_unref (l->data);
+ }
+
+ g_slist_free (objects);
+ objects = NULL;
+ }
+ }
+
+ void
+ tracker_dbus_shutdown (void)
+ {
+ dbus_set_available (FALSE);
+
+ if (backup) {
+ dbus_g_connection_unregister_g_object (connection, G_OBJECT (backup));
+ g_object_unref (backup);
+ }
+
+ if (notifier) {
+ dbus_g_connection_unregister_g_object (connection, G_OBJECT (notifier));
+ g_object_unref (notifier);
+ }
+
+ if (gproxy) {
+ g_object_unref (gproxy);
+ gproxy = NULL;
+ }
+
+ connection = NULL;
+ }
+#endif
+
+ public static Tracker.Status? register_notifier () {
+ if (connection == null /* || !gproxy */) {
+ critical ("D-Bus support must be initialized before registering objects!");
+ return null;
+ }
+
+ /* Add org.freedesktop.Tracker */
+ notifier = new Tracker.Status ();
+ if (notifier == null) {
+ critical ("Could not create TrackerStatus object to register");
+ return null;
+ }
+
+ register_object (connection, notifier, Tracker.Status.PATH);
+
+ return notifier;
+ }
+
+ public static bool register_objects () {
+ //gpointer object, resources;
+
+ if (connection == null /*|| !gproxy*/) {
+ critical ("D-Bus support must be initialized before registering objects!");
+ return false;
+ }
+
+#if 0
+ /* Add org.freedesktop.Tracker */
+ object = tracker_statistics_new ();
+ if (!object) {
+ g_critical ("Could not create TrackerStatistics object to register");
+ return FALSE;
+ }
+
+ dbus_register_object (connection,
+ gproxy,
+ G_OBJECT (object),
+ &dbus_glib_tracker_statistics_object_info,
+ TRACKER_STATISTICS_PATH);
+ objects = g_slist_prepend (objects, object);
+#endif
+
+ /* Add org.freedesktop.Tracker1.Resources */
+ var resources = new Tracker.Resources (connection);
+ if (resources == null) {
+ critical ("Could not create TrackerResources object to register");
+ return false;
+ }
+
+#if 0
+ dbus_g_proxy_connect_signal (gproxy, "NameOwnerChanged",
+ G_CALLBACK (name_owner_changed_cb),
+ object,
+ name_owner_changed_closure);
+#endif
+
+ register_object (connection, resources, Tracker.Resources.PATH);
+ //objects = g_slist_prepend (objects, object);
+
+ /* Add org.freedesktop.Tracker1.Steroids */
+ var steroids = new Tracker.Steroids ();
+ if (steroids == null) {
+ critical ("Could not create TrackerSteroids object to register");
+ return false;
+ }
+
+ register_object (connection, steroids, Tracker.Steroids.PATH);
+ //objects = g_slist_prepend (objects, object);
+
+#if 0
+ /* Reverse list since we added objects at the top each time */
+ objects = g_slist_reverse (objects);
+
+ if (!backup) {
+ /* Add org.freedesktop.Tracker1.Backup */
+ backup = tracker_backup_new ();
+ if (!backup) {
+ g_critical ("Could not create TrackerBackup object to register");
+ return FALSE;
+ }
+
+ dbus_register_object (connection,
+ gproxy,
+ G_OBJECT (backup),
+ &dbus_glib_tracker_backup_object_info,
+ TRACKER_BACKUP_PATH);
+ /* Backup object isn't part of the linked list, set_available wouldn't
+ * work correctly from the dbus call otherwise */
+ }
+#endif
+
+ return true;
+ }
+
+#if 0
+ gboolean
+ tracker_dbus_register_prepare_class_signal (void)
+ {
+ gpointer resources;
+
+ resources = tracker_dbus_get_object (TRACKER_TYPE_RESOURCES);
+
+ if (!resources) {
+ g_message ("Error during initialization, Resources DBus object not available");
+ return FALSE;
+ }
+
+ tracker_resources_enable_signals (resources);
+
+ return TRUE;
+ }
+
+ GObject *
+ tracker_dbus_get_object (GType type)
+ {
+ GSList *l;
+
+ for (l = objects; l; l = l->next) {
+ if (G_OBJECT_TYPE (l->data) == type) {
+ return l->data;
+ }
+ }
+
+ if (steroids && type == TRACKER_TYPE_STEROIDS) {
+ return G_OBJECT (steroids);
+ }
+
+ if (notifier && type == TRACKER_TYPE_STATUS) {
+ return G_OBJECT (notifier);
+ }
+
+ if (backup && type == TRACKER_TYPE_BACKUP) {
+ return G_OBJECT (backup);
+ }
+
+ return NULL;
+ }
+#endif
+}
diff --git a/src/tracker-store/tracker-events.c b/src/tracker-store/tracker-events.c
index eafeff6..435025f 100644
--- a/src/tracker-store/tracker-events.c
+++ b/src/tracker-store/tracker-events.c
@@ -20,6 +20,8 @@
* Philip Van Hoof <philip codeminded be>
*/
+#if 0
+
#include "config.h"
#include <libtracker-data/tracker-data.h>
@@ -241,3 +243,5 @@ tracker_events_shutdown (void)
g_warning ("tracker_events already shutdown");
}
}
+
+#endif
diff --git a/src/tracker-store/tracker-locale-change.c b/src/tracker-store/tracker-locale-change.c
index 5a7495c..7c02148 100644
--- a/src/tracker-store/tracker-locale-change.c
+++ b/src/tracker-store/tracker-locale-change.c
@@ -17,6 +17,8 @@
* Boston, MA 02110-1301, USA.
*/
+#if 0
+
#include "config.h"
#include <stdlib.h>
@@ -140,3 +142,5 @@ tracker_locale_change_shutdown_subscription (void)
{
tracker_locale_notify_remove (locale_notification_id);
}
+
+#endif
diff --git a/src/tracker-store/tracker-main.vala b/src/tracker-store/tracker-main.vala
new file mode 100644
index 0000000..83a1a19
--- /dev/null
+++ b/src/tracker-store/tracker-main.vala
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2006, Jamie McCracken <jamiemcc gnome org>
+ * Copyright (C) 2008, Nokia <ivan frade nokia com>
+ *
+ * This library 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 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 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.Main {
+#if 0
+
+//const string ABOUT = "Tracker " PACKAGE_VERSION "\n";
+
+const string LICENSE = "This program is free software and comes without any warranty.
+It is licensed under version 2 or later of the General Public
+License which can be viewed at:
+ http://www.gnu.org/licenses/gpl.txt
+";
+
+#endif
+
+ const int SELECT_CACHE_SIZE = 100;
+ const int UPDATE_CACHE_SIZE = 100;
+
+ static MainLoop main_loop;
+ static string log_filename;
+
+ static string ttl_backup_file;
+
+ static bool first_time_index;
+ static bool reindex_on_shutdown;
+ static bool shutdown;
+
+/* Private command line parameters */
+ static bool version;
+ static int verbosity = -1;
+ static bool force_reindex;
+ static bool readonly_mode;
+
+ const OptionEntry entries[] = {
+ /* Daemon options */
+ { "version", 'V', 0, OptionArg.NONE, ref version, N_("Displays version information"), null },
+ { "verbosity", 'v', 0, OptionArg.INT, ref verbosity, N_("Logging, 0 = errors only, 1 = minimal, 2 = detailed and 3 = debug (default = 0)"), null },
+
+ /* Indexer options */
+ { "force-reindex", 'r', 0, OptionArg.NONE, ref force_reindex, N_("Force a re-index of all content"), null },
+ { "readonly-mode", 'n', 0, OptionArg.NONE, ref readonly_mode, N_("Only allow read based actions on the database"), null },
+ { null }
+ };
+
+#if 0
+static void
+private_free (gpointer data)
+{
+ TrackerMainPrivate *private;
+
+ private = data;
+
+ g_free (private->ttl_backup_file);
+ g_free (private->log_filename);
+
+ g_main_loop_unref (private->main_loop);
+
+ g_free (private);
+}
+
+static void
+sanity_check_option_values (TrackerConfig *config)
+{
+ g_message ("General options:");
+ g_message (" Verbosity ............................ %d",
+ tracker_config_get_verbosity (config));
+
+ g_message ("Store options:");
+ g_message (" Readonly mode ........................ %s",
+ readonly_mode ? "yes" : "no");
+}
+#endif
+
+ static void do_shutdown () {
+ if (main_loop != null) {
+ main_loop.quit ();
+ }
+
+ shutdown = true;
+ }
+
+#if 0
+static gboolean
+shutdown_timeout_cb (gpointer user_data)
+{
+ g_critical ("Could not exit in a timely fashion - terminating...");
+ exit (EXIT_FAILURE);
+
+ return FALSE;
+}
+
+static void
+signal_handler (int signo)
+{
+ static gboolean in_loop = FALSE;
+
+ /* Die if we get re-entrant signals handler calls */
+ if (in_loop) {
+ _exit (EXIT_FAILURE);
+ }
+
+ switch (signo) {
+ case SIGTERM:
+ case SIGINT:
+ in_loop = TRUE;
+ do_shutdown ();
+
+ /* Fall through */
+ default:
+ if (g_strsignal (signo)) {
+ g_print ("\n");
+ g_print ("Received signal:%d->'%s'",
+ signo,
+ g_strsignal (signo));
+ }
+ break;
+ }
+}
+
+static void
+initialize_signal_handler (void)
+{
+ struct sigaction act;
+ sigset_t empty_mask;
+
+ sigemptyset (&empty_mask);
+ act.sa_handler = signal_handler;
+ act.sa_mask = empty_mask;
+ act.sa_flags = 0;
+
+ sigaction (SIGTERM, &act, NULL);
+ sigaction (SIGINT, &act, NULL);
+ sigaction (SIGHUP, &act, NULL);
+}
+
+static void
+initialize_priority (void)
+{
+ /* Set disk IO priority and scheduling */
+ tracker_ioprio_init ();
+
+ /* NOTE: We only set the nice() value when crawling, for all
+ * other times we don't have a nice() value. Check the
+ * tracker-status code to see where this is done.
+ */
+}
+
+static void
+initialize_directories (void)
+{
+ /* NOTE: We don't create the database directories here, the
+ * tracker-db-manager does that for us.
+ */
+}
+
+static void
+shutdown_databases (void)
+{
+#if 0
+ TrackerMainPrivate *private;
+
+ private = g_static_private_get (&private_key);
+
+ /* TODO port backup support */
+
+ /* If we are reindexing, save the user metadata */
+ if (private->reindex_on_shutdown) {
+ tracker_data_backup_save (private->ttl_backup_file, NULL);
+ }
+#endif
+}
+
+static void
+shutdown_directories (void)
+{
+ TrackerMainPrivate *private;
+
+ private = g_static_private_get (&private_key);
+
+ /* If we are reindexing, just remove the databases */
+ if (private->reindex_on_shutdown) {
+ tracker_db_manager_remove_all (FALSE);
+ }
+}
+
+static GStrv
+get_notifiable_classes (void)
+{
+ TrackerDBResultSet *result_set;
+ GStrv classes_to_signal = NULL;
+
+ result_set = tracker_data_query_sparql ("SELECT ?class WHERE { "
+ " ?class tracker:notify true "
+ "}",
+ NULL);
+
+ if (result_set) {
+ guint count = 0;
+
+ classes_to_signal = tracker_dbus_query_result_to_strv (result_set,
+ 0,
+ &count);
+ g_object_unref (result_set);
+ }
+
+ return classes_to_signal;
+}
+
+
+static GStrv
+get_writeback_predicates (void)
+{
+ TrackerDBResultSet *result_set;
+ GStrv predicates_to_signal = NULL;
+
+ result_set = tracker_data_query_sparql ("SELECT ?predicate WHERE { "
+ " ?predicate tracker:writeback true "
+ "}",
+ NULL);
+
+ if (result_set) {
+ guint count = 0;
+
+ predicates_to_signal = tracker_dbus_query_result_to_strv (result_set,
+ 0,
+ &count);
+ g_object_unref (result_set);
+ }
+
+ return predicates_to_signal;
+}
+
+static void
+config_verbosity_changed_cb (GObject *object,
+ GParamSpec *spec,
+ gpointer user_data)
+{
+ gint verbosity;
+
+ verbosity = tracker_config_get_verbosity (TRACKER_CONFIG (object));
+
+ g_message ("Log verbosity is set to %d, %s D-Bus client lookup",
+ verbosity,
+ verbosity > 0 ? "enabling" : "disabling");
+
+ tracker_dbus_enable_client_lookup (verbosity > 0);
+}
+
+#endif
+
+ static int main (string args[]) {
+#if 0
+ GError *error = NULL;
+ TrackerConfig *config;
+ gint chunk_size_mb;
+ gsize chunk_size;
+ const gchar *rotate_to;
+ TrackerDBConfig *db_config;
+ gboolean do_rotating;
+#endif
+
+ Intl.setlocale (LocaleCategory.ALL, "");
+
+#if 0
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ /* Set timezone info */
+ tzset ();
+#endif
+
+ try {
+ /* Translators: this messagge will apper immediately after the
+ * usage string - Usage: COMMAND <THIS_MESSAGE>
+ */
+ var context = new OptionContext (_("- start the tracker daemon"));
+ context.add_main_entries (entries, null);
+ context.parse (ref args);
+ } catch (Error e) {
+ printerr ("Invalid arguments, %s\n", e.message);
+ return 1;
+ }
+
+ if (version) {
+ /* Print information */
+ //print ("\n" ABOUT "\n" LICENSE "\n");
+ return 0;
+ }
+
+ print ("Initializing tracker-store...\n");
+
+#if 0
+ initialize_signal_handler ();
+
+ /* Check XDG spec locations XDG_DATA_HOME _MUST_ be writable. */
+ if (!tracker_env_check_xdg_dirs ()) {
+ return EXIT_FAILURE;
+ }
+
+ /* This makes sure we don't steal all the system's resources */
+ initialize_priority ();
+
+ /* Public locations */
+ private->ttl_backup_file =
+ g_build_filename (g_get_user_data_dir (),
+ "tracker",
+ "data",
+ "tracker-userdata-backup.ttl",
+ NULL);
+
+ /* Initialize major subsystems */
+ config = tracker_config_new ();
+ db_config = tracker_db_config_new ();
+
+ g_signal_connect (config, "notify::verbosity",
+ G_CALLBACK (config_verbosity_changed_cb),
+ NULL);
+
+ /* Daemon command line arguments */
+ if (verbosity > -1) {
+ tracker_config_set_verbosity (config, verbosity);
+ } else {
+ /* Make sure we enable/disable the dbus client lookup */
+ config_verbosity_changed_cb (G_OBJECT (config), NULL, NULL);
+ }
+
+ initialize_directories ();
+#endif
+
+ if (!Tracker.DBus.init ()) {
+ return 1;
+ }
+
+ /* Initialize other subsystems */
+ Tracker.Log.init (3 /*tracker_config_get_verbosity (config)*/, out log_filename);
+ print ("Starting log:\n File:'%s'\n", log_filename);
+
+#if 0
+ sanity_check_option_values (config);
+#endif
+
+ DBManagerFlags flags = DBManagerFlags.REMOVE_CACHE;
+
+ if (force_reindex) {
+ /* TODO port backup support
+ backup_user_metadata (config, language); */
+
+ flags |= DBManagerFlags.FORCE_REINDEX;
+ }
+
+ var notifier = Tracker.DBus.register_notifier ();
+ var busy_callback = notifier.get_callback ();
+
+ Tracker.Store.init ();
+
+ /* Make Tracker available for introspection */
+ if (!Tracker.DBus.register_objects ()) {
+ return 1;
+ }
+
+ if (!Tracker.DBus.register_names ()) {
+ return 1;
+ }
+
+#if 0
+ chunk_size_mb = tracker_db_config_get_journal_chunk_size (db_config);
+ chunk_size = (gsize) ((gsize) chunk_size_mb * (gsize) 1024 * (gsize) 1024);
+ rotate_to = tracker_db_config_get_journal_rotate_destination (db_config);
+
+ if (rotate_to[0] == '\0')
+ rotate_to = NULL;
+
+ do_rotating = (chunk_size_mb != -1);
+
+ tracker_db_journal_set_rotating (do_rotating, chunk_size, rotate_to);
+#endif
+
+ int select_cache_size, update_cache_size;
+ string cache_size_s;
+
+ cache_size_s = Environment.get_variable ("TRACKER_STORE_SELECT_CACHE_SIZE");
+ if (cache_size_s != null && cache_size_s != "") {
+ select_cache_size = cache_size_s.to_int ();
+ } else {
+ select_cache_size = SELECT_CACHE_SIZE;
+ }
+
+ cache_size_s = Environment.get_variable ("TRACKER_STORE_UPDATE_CACHE_SIZE");
+ if (cache_size_s != null && cache_size_s != "") {
+ update_cache_size = cache_size_s.to_int ();
+ } else {
+ update_cache_size = UPDATE_CACHE_SIZE;
+ }
+
+ bool is_first_time_index;
+
+ if (!Tracker.Data.Manager.init (flags,
+ null,
+ out is_first_time_index,
+ true,
+ select_cache_size,
+ update_cache_size,
+ busy_callback,
+ "Initializing")) {
+
+ return 1;
+ }
+
+
+#if 0
+ g_object_unref (db_config);
+ g_object_unref (notifier);
+#endif
+
+ if (!shutdown) {
+#if 0
+ /* Setup subscription to get notified of locale changes */
+ tracker_locale_change_initialize_subscription ();
+
+ tracker_dbus_register_prepare_class_signal ();
+
+ tracker_events_init (get_notifiable_classes);
+ tracker_writeback_init (get_writeback_predicates);
+#endif
+ Tracker.Store.set_active (true, null);
+
+ message ("Waiting for D-Bus requests...");
+ }
+
+ /* Set our status as running, if this is FALSE, threads stop
+ * doing what they do and shutdown.
+ */
+ if (!shutdown) {
+ main_loop = new MainLoop ();
+ main_loop.run ();
+ }
+
+ /*
+ * Shutdown the daemon
+ */
+ message ("Shutdown started");
+
+#if 0
+ tracker_store_shutdown ();
+
+ g_timeout_add_full (G_PRIORITY_LOW, 5000, shutdown_timeout_cb, NULL, NULL);
+
+ g_message ("Cleaning up");
+
+ shutdown_databases ();
+ shutdown_directories ();
+
+ /* Shutdown major subsystems */
+ tracker_writeback_shutdown ();
+ tracker_events_shutdown ();
+
+ tracker_locale_change_shutdown_subscription ();
+
+ tracker_dbus_shutdown ();
+ tracker_data_manager_shutdown ();
+ tracker_log_shutdown ();
+
+ g_signal_handlers_disconnect_by_func (config, config_verbosity_changed_cb, NULL);
+ g_object_unref (config);
+
+ /* This will free rotate_to up in the journal code */
+ tracker_db_journal_set_rotating ((chunk_size_mb != -1), chunk_size, NULL);
+#endif
+
+ print ("\nOK\n\n");
+
+ return 0;
+ }
+}
diff --git a/src/tracker-store/tracker-resources.vala b/src/tracker-store/tracker-resources.vala
new file mode 100644
index 0000000..b4ab7d4
--- /dev/null
+++ b/src/tracker-store/tracker-resources.vala
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2006, Jamie McCracken <jamiemcc gnome org>
+ * Copyright (C) 2008, Nokia <ivan frade nokia com>
+ *
+ * This library 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 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 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.
+ */
+
+#if 0
+
+const int TRACKER_GRAPH_UPDATED_IMMEDIATE_EMIT_AT = 1000;
+const int TRACKER_SIGNALS_SECONDS_PER_EMIT = 1;
+
+//#define RDF_PREFIX TRACKER_RDF_PREFIX
+//#define RDF_TYPE RDF_PREFIX "type"
+
+/* I *know* that this is some arbitrary number that doesn't seem to
+ * resemble anything. In fact it's what I experimentally measured to
+ * be a good value on a default Debian testing which has
+ * max_message_size set to 1 000 000 000 in session.conf. I didn't have
+ * the feeling that this value was very much respected, as the size
+ * of the DBusMessage when libdbus decided to exit() the process was
+ * around 160 MB, and not ~ 1000 MB. So if you take 160 MB and you
+ * devide it by 1000000 you have an average string size of ~ 160
+ * bytes plus DBusMessage's overhead. If that makes this number less
+ * arbitrary for you, then fine.
+ *
+ * I really hope that the libdbus people get to their senses and
+ * either stop doing their exit() nonsense in a library, and instead
+ * return a clean DBusError or something, or create crystal clear
+ * clarity about the maximum size of a message. And make it both so
+ * that I can get this length at runtime (without having to parse
+ * libdbus's own configuration files) and my DBusMessage's current
+ * total length. As far as I know are both not possible. So that for
+ * me means that libdbus's exit() is unacceptable.
+ *
+ * Note for the debugger of the future, the "Disconnected" signal gets
+ * sent to us by the bus, which in turn makes libdbus-glib perform exit(). */
+
+const int DBUS_ARBITRARY_MAX_MSG_SIZE = 1000000;
+#endif
+
+[DBus (name = "org.freedesktop.Tracker1.Resources")]
+class Tracker.Resources : Object {
+ public const string PATH = "/org/freedesktop/Tracker1/Resources";
+#if 0
+ enum {
+ WRITEBACK,
+ GRAPHUPDATED,
+ LAST_SIGNAL
+ };
+
+ typedef struct {
+ DBusConnection *connection;
+ guint signal_timeout;
+ } TrackerResourcesPrivate;
+
+ typedef struct {
+ DBusGMethodInvocation *context;
+ guint request_id;
+ DBusMessage *reply;
+ } TrackerDBusMethodInfo;
+
+ typedef struct {
+ DBusMessage *reply;
+ GError *error;
+ gpointer user_data;
+ } InThreadPtr;
+
+ static void tracker_resources_finalize (GObject *object);
+ static guint signals[LAST_SIGNAL] = { 0 };
+
+ static void
+ tracker_resources_class_init (TrackerResourcesClass *klass)
+ {
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_resources_finalize;
+
+ signals[WRITEBACK] =
+ g_signal_new ("writeback",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerResourcesClass, writeback),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ TRACKER_TYPE_INT_ARRAY_MAP);
+
+ /* This is just for introspection to work */
+ signals[GRAPHUPDATED] =
+ g_signal_new ("graph-updated",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerResourcesClass, graph_updated),
+ NULL, NULL,
+ tracker_marshal_VOID__STRING_BOXED_BOXED,
+ G_TYPE_NONE, 3,
+ G_TYPE_STRING,
+ TRACKER_TYPE_FOUR_INT_ARRAY,
+ TRACKER_TYPE_FOUR_INT_ARRAY);
+
+ g_type_class_add_private (object_class, sizeof (TrackerResourcesPrivate));
+ }
+#endif
+
+ public Resources (DBusConnection connection) {
+#if 0
+ TrackerResourcesPrivate *priv;
+ TrackerResources *resources = g_object_new (TRACKER_TYPE_RESOURCES, NULL);
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (resources);
+
+ priv->connection = dbus_connection_ref (dbus_g_connection_get_connection (connection));
+#endif
+ }
+
+ /*
+ * Functions
+ */
+
+#if 0
+ static void
+ destroy_method_info (gpointer user_data)
+ {
+ g_slice_free (TrackerDBusMethodInfo, user_data);
+ }
+
+ static void
+ turtle_import_callback (GError *error, gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &error,
+ NULL);
+ dbus_g_method_return_error (info->context, error);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id,
+ info->context);
+ dbus_g_method_return (info->context);
+ }
+#endif
+
+ public void load (string uri) throws Error {
+#if 0
+ TrackerDBusMethodInfo *info;
+ guint request_id;
+ GFile *file;
+ gchar *sender;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_async_return_if_fail (uri != NULL, context);
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "%s(): uri:'%s'",
+ __FUNCTION__,
+ uri);
+
+ file = g_file_new_for_uri (uri);
+
+ info = g_slice_new (TrackerDBusMethodInfo);
+
+ info->request_id = request_id;
+ info->context = context;
+
+ sender = dbus_g_method_get_sender (context);
+
+ tracker_store_queue_turtle_import (file, turtle_import_callback,
+ sender, info, destroy_method_info);
+
+ g_free (sender);
+ g_object_unref (file);
+#endif
+ }
+
+#if 0
+ static void
+ query_callback (gpointer inthread_data, GError *error, gpointer user_data)
+ {
+ InThreadPtr *ptr = inthread_data;
+ TrackerDBusMethodInfo *info = user_data;
+
+ if (ptr && ptr->error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &ptr->error,
+ NULL);
+ dbus_g_method_return_error (info->context, ptr->error);
+ g_error_free (ptr->error);
+ } else if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &error,
+ NULL);
+ dbus_g_method_return_error (info->context, error);
+ } else if (ptr) {
+ tracker_dbus_request_success (info->request_id,
+ info->context);
+
+ dbus_g_method_send_reply (info->context, ptr->reply);
+ } /* else, !ptr && !error... shouldn't happen */
+
+ if (ptr)
+ g_slice_free (InThreadPtr, ptr);
+ }
+
+ static gpointer
+ query_inthread (TrackerDBCursor *cursor, GCancellable *cancellable, GError *error, gpointer user_data)
+ {
+ InThreadPtr *ptr = g_slice_new0 (InThreadPtr);
+ TrackerDBusMethodInfo *info = user_data;
+ DBusMessage *reply;
+ DBusMessageIter iter, rows_iter;
+ guint cols;
+ GError *loop_error = NULL;
+ guint length = 0;
+ gboolean cont;
+
+ if (error) {
+ ptr->error = g_error_copy (error);
+ return ptr;
+ }
+
+ reply = info->reply;
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ cols = tracker_db_cursor_get_n_columns (cursor);
+
+ dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ "as",
+ &rows_iter);
+
+ cont = TRUE;
+
+ while (tracker_db_cursor_iter_next (cursor, cancellable, &loop_error) && cont) {
+ DBusMessageIter cols_iter;
+ guint i;
+
+ if (loop_error != NULL) {
+ break;
+ }
+
+ dbus_message_iter_open_container (&rows_iter,
+ DBUS_TYPE_ARRAY,
+ "s",
+ &cols_iter);
+
+ for (i = 0; i < cols && cont; i++, length++) {
+ const gchar *result_str;
+ result_str = tracker_db_cursor_get_string (cursor, i, NULL);
+
+ if (result_str == NULL)
+ result_str = "";
+
+ dbus_message_iter_append_basic (&cols_iter, DBUS_TYPE_STRING, &result_str);
+
+ if (length > DBUS_ARBITRARY_MAX_MSG_SIZE) {
+ g_set_error (&loop_error,
+ TRACKER_DB_INTERFACE_ERROR,
+ TRACKER_DB_INTERRUPTED,
+ "result set of the query is too large");
+
+ cont = FALSE;
+ }
+
+ }
+
+ dbus_message_iter_close_container (&rows_iter, &cols_iter);
+ }
+
+ dbus_message_iter_close_container (&iter, &rows_iter);
+
+ if (loop_error) {
+ ptr->error = loop_error;
+ ptr->reply = NULL;
+ } else {
+ ptr->reply = reply;
+ }
+
+ return ptr;
+ }
+
+ void
+ tracker_resources_sparql_query (TrackerResources *self,
+ const gchar *query,
+ DBusGMethodInvocation *context,
+ GError **error)
+ {
+ TrackerDBusMethodInfo *info;
+ guint request_id;
+ gchar *sender;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_async_return_if_fail (query != NULL, context);
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "%s(): '%s'",
+ __FUNCTION__,
+ query);
+
+ info = g_slice_new (TrackerDBusMethodInfo);
+
+ info->request_id = request_id;
+ info->context = context;
+ info->reply = dbus_g_method_get_reply (context);
+
+ sender = dbus_g_method_get_sender (context);
+
+ tracker_store_sparql_query (query, TRACKER_STORE_PRIORITY_HIGH,
+ query_inthread, query_callback, sender,
+ info, destroy_method_info);
+
+ g_free (sender);
+ }
+
+ static void
+ update_callback (GError *error, gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &error,
+ NULL);
+ dbus_g_method_return_error (info->context, error);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id,
+ info->context);
+ dbus_g_method_return (info->context);
+ }
+
+ void
+ tracker_resources_sparql_update (TrackerResources *self,
+ const gchar *update,
+ DBusGMethodInvocation *context,
+ GError **error)
+ {
+ TrackerDBusMethodInfo *info;
+ guint request_id;
+ gchar *sender;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_async_return_if_fail (update != NULL, context);
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "%s(): '%s'",
+ __FUNCTION__,
+ update);
+
+ info = g_slice_new (TrackerDBusMethodInfo);
+
+ info->request_id = request_id;
+ info->context = context;
+
+ sender = dbus_g_method_get_sender (context);
+
+ tracker_store_sparql_update (update, TRACKER_STORE_PRIORITY_HIGH,
+ update_callback, sender,
+ info, destroy_method_info);
+
+ g_free (sender);
+ }
+
+ static void
+ update_blank_callback (GPtrArray *blank_nodes, GError *error, gpointer user_data)
+ {
+ TrackerDBusMethodInfo *info = user_data;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ info->context,
+ &error,
+ NULL);
+ dbus_g_method_return_error (info->context, error);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id,
+ info->context);
+ dbus_g_method_return (info->context, blank_nodes);
+ }
+
+ void
+ tracker_resources_sparql_update_blank (TrackerResources *self,
+ const gchar *update,
+ DBusGMethodInvocation *context,
+ GError **error)
+ {
+ TrackerDBusMethodInfo *info;
+ guint request_id;
+ gchar *sender;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_async_return_if_fail (update != NULL, context);
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "%s(): '%s'",
+ __FUNCTION__,
+ update);
+
+ info = g_slice_new (TrackerDBusMethodInfo);
+
+ info->request_id = request_id;
+ info->context = context;
+
+ sender = dbus_g_method_get_sender (context);
+
+ tracker_store_sparql_update_blank (update, TRACKER_STORE_PRIORITY_HIGH,
+ update_blank_callback, sender,
+ info, destroy_method_info);
+
+ g_free (sender);
+ }
+
+ void
+ tracker_resources_sync (TrackerResources *self,
+ DBusGMethodInvocation *context,
+ GError **error)
+ {
+ guint request_id;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "%s()",
+ __FUNCTION__);
+
+ tracker_data_sync ();
+
+ tracker_dbus_request_success (request_id, context);
+ dbus_g_method_return (context);
+ }
+
+ void
+ tracker_resources_batch_sparql_update (TrackerResources *self,
+ const gchar *update,
+ DBusGMethodInvocation *context,
+ GError **error)
+ {
+ TrackerDBusMethodInfo *info;
+ guint request_id;
+ gchar *sender;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_async_return_if_fail (update != NULL, context);
+
+ tracker_dbus_request_new (request_id,
+ context,
+ "%s(): '%s'",
+ __FUNCTION__,
+ update);
+
+ info = g_slice_new (TrackerDBusMethodInfo);
+
+ info->request_id = request_id;
+ info->context = context;
+
+ sender = dbus_g_method_get_sender (context);
+
+ tracker_store_sparql_update (update, TRACKER_STORE_PRIORITY_LOW,
+ update_callback, sender,
+ info, destroy_method_info);
+
+ g_free (sender);
+ }
+
+ void
+ tracker_resources_batch_commit (TrackerResources *self,
+ DBusGMethodInvocation *context,
+ GError **error)
+ {
+ /* no longer needed, just return */
+ dbus_g_method_return (context);
+ }
+
+ static void
+ foreach_add_to_iter (gint graph_id,
+ gint subject_id,
+ gint pred_id,
+ gint object_id,
+ gpointer user_data)
+ {
+ DBusMessageIter *array_iter = user_data;
+ DBusMessageIter struct_iter;
+
+ dbus_message_iter_open_container (array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter);
+ dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_INT32, &graph_id);
+ dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_INT32, &subject_id);
+ dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_INT32, &pred_id);
+ dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_INT32, &object_id);
+ dbus_message_iter_close_container (array_iter, &struct_iter);
+ }
+
+ static gboolean
+ emit_graph_updated (TrackerResources *self,
+ TrackerClass *class)
+ {
+ if (tracker_class_has_insert_events (class) || tracker_class_has_delete_events (class)) {
+ TrackerResourcesPrivate *priv;
+ DBusMessageIter iter, deletes_iter, inserts_iter;
+ DBusMessage *message;
+ const gchar *class_uri;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (self);
+
+ message = dbus_message_new_signal (TRACKER_RESOURCES_PATH,
+ TRACKER_RESOURCES_INTERFACE,
+ "GraphUpdated");
+
+ class_uri = tracker_class_get_uri (class);
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &class_uri);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+ "(iiii)", &deletes_iter);
+
+ tracker_class_foreach_delete_event (class, foreach_add_to_iter, &deletes_iter);
+
+ dbus_message_iter_close_container (&iter, &deletes_iter);
+
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+ "(iiii)", &inserts_iter);
+
+ tracker_class_foreach_insert_event (class, foreach_add_to_iter, &inserts_iter);
+
+ dbus_message_iter_close_container (&iter, &inserts_iter);
+
+ dbus_connection_send (priv->connection, message, NULL);
+
+ dbus_message_unref (message);
+
+ tracker_class_reset_ready_events (class);
+
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ static gboolean
+ on_emit_signals (gpointer user_data)
+ {
+ TrackerResources *resources = user_data;
+ TrackerResourcesPrivate *priv;
+ GHashTableIter iter;
+ gpointer key, value;
+ gboolean had_any = FALSE;
+ GHashTable *writebacks;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (resources);
+
+ /* Class signal feature */
+ tracker_events_classes_iter (&iter);
+
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ TrackerClass *class = key;
+ if (emit_graph_updated (user_data, class)) {
+ had_any = TRUE;
+ }
+ }
+
+ /* Reset counter */
+ tracker_events_get_total (TRUE);
+
+
+ /* Writeback feature */
+ writebacks = tracker_writeback_get_ready ();
+
+ if (writebacks) {
+ had_any = TRUE;
+ g_signal_emit (resources, signals[WRITEBACK], 0, writebacks);
+ }
+
+ tracker_writeback_reset_ready ();
+
+ if (!had_any)
+ priv->signal_timeout = 0;
+
+ return had_any;
+ }
+
+ static void
+ on_statements_committed (gboolean start_timer,
+ gpointer user_data)
+ {
+ TrackerResources *resources = user_data;
+ TrackerResourcesPrivate *priv;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ /* Class signal feature */
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (resources);
+
+ /* Class signal feature */
+ tracker_events_classes_iter (&iter);
+
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ TrackerClass *class = key;
+ tracker_class_transact_events (class);
+ }
+
+ if (start_timer && priv->signal_timeout == 0) {
+ priv->signal_timeout = g_timeout_add_seconds (TRACKER_SIGNALS_SECONDS_PER_EMIT,
+ on_emit_signals,
+ user_data);
+ }
+
+ /* Writeback feature */
+ tracker_writeback_transact ();
+ }
+
+
+ static void
+ on_statements_rolled_back (gboolean start_timer,
+ gpointer user_data)
+ {
+ tracker_events_reset_pending ();
+ tracker_writeback_reset_pending ();
+ }
+
+ static void
+ check_graph_updated_signal (TrackerResources *object)
+ {
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ /* Check for whether we need an immediate emit */
+ if (tracker_events_get_total (FALSE) > TRACKER_GRAPH_UPDATED_IMMEDIATE_EMIT_AT) {
+ gpointer key, value;
+ GHashTableIter iter;
+
+ tracker_events_classes_iter (&iter);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ TrackerClass *class = key;
+ emit_graph_updated (object, class);
+ }
+
+ /* Reset counter */
+ tracker_events_get_total (TRUE);
+ }
+ }
+
+ static void
+ on_statement_inserted (gint graph_id,
+ const gchar *graph,
+ gint subject_id,
+ const gchar *subject,
+ gint pred_id,
+ gint object_id,
+ const gchar *object,
+ GPtrArray *rdf_types,
+ gpointer user_data)
+ {
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (user_data);
+
+ tracker_events_add_insert (graph_id, subject_id, subject, pred_id,
+ object_id, object, rdf_types);
+ tracker_writeback_check (graph_id, graph, subject_id,
+ subject, pred_id, object_id,
+ object, rdf_types);
+ check_graph_updated_signal (user_data);
+ }
+
+ static void
+ on_statement_deleted (gint graph_id,
+ const gchar *graph,
+ gint subject_id,
+ const gchar *subject,
+ gint pred_id,
+ gint object_id,
+ const gchar *object,
+ GPtrArray *rdf_types,
+ gpointer user_data)
+ {
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (user_data);
+
+ tracker_events_add_delete (graph_id, subject_id, subject, pred_id,
+ object_id, object, rdf_types);
+ tracker_writeback_check (graph_id, graph, subject_id,
+ subject, pred_id, object_id,
+ object, rdf_types);
+ check_graph_updated_signal (user_data);
+ }
+
+ void
+ tracker_resources_enable_signals (TrackerResources *object)
+ {
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ tracker_data_add_insert_statement_callback (on_statement_inserted, object);
+ tracker_data_add_delete_statement_callback (on_statement_deleted, object);
+ tracker_data_add_commit_statement_callback (on_statements_committed, object);
+ tracker_data_add_rollback_statement_callback (on_statements_rolled_back, object);
+ }
+
+ void
+ tracker_resources_disable_signals (TrackerResources *object)
+ {
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ tracker_data_remove_insert_statement_callback (on_statement_inserted, object);
+ tracker_data_remove_delete_statement_callback (on_statement_deleted, object);
+ tracker_data_remove_commit_statement_callback (on_statements_committed, object);
+ tracker_data_remove_rollback_statement_callback (on_statements_rolled_back, object);
+
+ if (priv->signal_timeout != 0) {
+ g_source_remove (priv->signal_timeout);
+ }
+ }
+
+ static void
+ tracker_resources_finalize (GObject *object)
+ {
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ tracker_resources_disable_signals ((TrackerResources *) object);
+
+ dbus_connection_unref (priv->connection);
+
+ G_OBJECT_CLASS (tracker_resources_parent_class)->finalize (object);
+ }
+
+ void
+ tracker_resources_unreg_batches (TrackerResources *object,
+ const gchar *old_owner)
+ {
+ tracker_store_unreg_batches (old_owner);
+ }
+#endif
+}
diff --git a/src/tracker-store/tracker-statistics.vala b/src/tracker-store/tracker-statistics.vala
new file mode 100644
index 0000000..f843433
--- /dev/null
+++ b/src/tracker-store/tracker-statistics.vala
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2006, Jamie McCracken <jamiemcc gnome org>
+ * Copyright (C) 2008, Nokia <ivan frade nokia com>
+ *
+ * This library 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 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 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.
+ */
+
+#if 0
+
+[DBus (name = "org.freedesktop.Tracker1.Statistics")]
+class Tracker.Statistics : Object {
+#if 0
+ static gint
+ cache_sort_func (gconstpointer a,
+ gconstpointer b)
+ {
+ const GStrv *strv_a = (GStrv *) a;
+ const GStrv *strv_b = (GStrv *) b;
+
+ g_return_val_if_fail (strv_a != NULL, 0);
+ g_return_val_if_fail (strv_b != NULL, 0);
+
+ return g_strcmp0 (*strv_a[0], *strv_b[0]);
+ }
+#endif
+
+ public new string[,] get () {
+ string[,] values = new string[0,0];
+ return values;
+#if 0
+ TrackerClass **classes, *cl;
+ guint request_id;
+ GPtrArray *values;
+ guint i, n_classes;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_request_new (request_id, context, "%s()", __FUNCTION__);
+
+ values = g_ptr_array_new ();
+
+ classes = tracker_ontologies_get_classes (&n_classes);
+
+ for (i = 0; i < n_classes; i++) {
+ GStrv strv;
+
+ cl = classes[i];
+
+ if (tracker_class_get_count (cl) == 0) {
+ /* skip classes without resources */
+ continue;
+ }
+
+ strv = g_new (gchar*, 3);
+ strv[0] = g_strdup (tracker_class_get_name (cl));
+ strv[1] = g_strdup_printf ("%d", tracker_class_get_count (cl));
+ strv[2] = NULL;
+
+ g_ptr_array_add (values, strv);
+ }
+
+ /* Sort result so it is alphabetical */
+ g_ptr_array_sort (values, cache_sort_func);
+
+ tracker_dbus_request_success (request_id, context);
+ dbus_g_method_return (context, values);
+
+ g_ptr_array_foreach (values, (GFunc) g_strfreev, NULL);
+ g_ptr_array_free (values, TRUE);
+#endif
+ }
+}
+
+#endif
diff --git a/src/tracker-store/tracker-status.vala b/src/tracker-store/tracker-status.vala
new file mode 100644
index 0000000..e17d231
--- /dev/null
+++ b/src/tracker-store/tracker-status.vala
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 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 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.
+ *
+ * Authors:
+ * Philip Van Hoof <philip codeminded be>
+ */
+
+[DBus (name = "org.freedesktop.Tracker1.Status")]
+class Tracker.Status : Object {
+ public const string PATH = "/org/freedesktop/Tracker1/Status";
+
+ const int PROGRESS_TIMEOUT_S = 5;
+
+ class WaitContext : Object {
+ public SourceFunc callback;
+ }
+
+ double progress;
+ string status = "Idle";
+ uint timer_id;
+ List<WaitContext> wait_list;
+
+#if 0
+ static void
+ tracker_status_class_init (TrackerStatusClass *klass)
+ {
+ /**
+ * TrackerStatus::progress:
+ * @notifier: the TrackerStatus
+ * @status: store status
+ * @progress: a #gdouble indicating store progress, from 0 to 1.
+ *
+ * the ::progress signal will be emitted by TrackerStatus
+ * to indicate progress about the store process. @status will
+ * contain a translated string with the current status and @progress
+ * will indicate how much has been processed so far.
+ **/
+ signals[PROGRESS] =
+ g_signal_new ("progress",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerStatusClass, progress),
+ NULL, NULL,
+ tracker_marshal_VOID__STRING_DOUBLE,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_DOUBLE);
+
+ g_type_class_add_private (object_class, sizeof (TrackerStatusPrivate));
+ }
+#endif
+
+ ~Status () {
+ if (timer_id != 0) {
+ Source.remove (timer_id);
+ }
+ }
+
+ bool
+ busy_notification_timeout () {
+ //progress (0, status, progress);
+
+ timer_id = 0;
+
+ return false;
+ }
+
+ static bool first_time = true;
+
+ void callback (string status, double progress) {
+ this.progress = progress;
+
+ if (progress == 1 && wait_list != null) {
+ /* notify clients that tracker-store is no longer busy */
+
+ wait_list.reverse ();
+ foreach (var context in wait_list) {
+ context.callback ();
+ }
+
+ wait_list = null;
+ }
+
+ if (status != this.status) {
+ this.status = status;
+ }
+
+ if (timer_id == 0) {
+ if (first_time) {
+ this.timer_id = Idle.add (busy_notification_timeout);
+ first_time = false;
+ } else {
+ timer_id = Timeout.add_seconds (PROGRESS_TIMEOUT_S, busy_notification_timeout);
+ }
+ }
+
+ /*while (g_main_context_iteration (NULL, FALSE))
+ ;*/
+ }
+
+ [DBus (visible = false)]
+ public BusyCallback get_callback () {
+ return callback;
+ }
+
+ public double get_progress () {
+ return this.progress;
+ }
+
+ public string get_status () {
+ return this.status;
+ }
+
+ public async void wait () throws Error {
+ if (progress == 1) {
+ /* tracker-store is idle */
+ } else {
+ var context = new WaitContext ();
+ context.callback = wait.callback;
+ wait_list.prepend (context);
+ yield;
+ }
+ }
+}
diff --git a/src/tracker-store/tracker-steroids.vala b/src/tracker-store/tracker-steroids.vala
new file mode 100644
index 0000000..eaa31f2
--- /dev/null
+++ b/src/tracker-store/tracker-steroids.vala
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) 2010, Codeminded BVBA <abustany gnome org>
+ *
+ * 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.
+ */
+
+const string UNKNOWN_METHOD_MESSAGE = "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist, expected \"%s\"";
+
+[DBus (name = "org.freedesktop.Tracker1.Steroids")]
+class Tracker.Steroids : Object {
+ public const string PATH = "/org/freedesktop/Tracker1/Steroids";
+
+ public const int BUFFER_SIZE = 65536;
+
+#if 0
+ typedef struct {
+ DBusMessage *call_message;
+ int fd;
+ guint request_id;
+ DBusConnection *connection;
+ struct {
+ int query_count;
+ int seen;
+ GPtrArray *errors;
+ } array_info;
+ } ClientInfo;
+
+ typedef struct {
+ GError *error;
+ gpointer user_data;
+ GStrv variable_names;
+ } InThreadPtr;
+
+ static void
+ tracker_steroids_class_init (TrackerSteroidsClass *klass)
+ {
+ }
+
+ static void
+ tracker_steroids_init (TrackerSteroids *object)
+ {
+ }
+
+ TrackerSteroids*
+ tracker_steroids_new (void)
+ {
+ return g_object_new (TRACKER_TYPE_STEROIDS, NULL);
+ }
+
+ static void
+ client_info_destroy (gpointer user_data)
+ {
+ ClientInfo *info = user_data;
+
+ dbus_message_unref (info->call_message);
+ dbus_connection_unref (info->connection);
+
+ g_slice_free (ClientInfo, user_data);
+ }
+
+ static void
+ query_callback (gpointer inthread_data,
+ GError *error,
+ gpointer user_data)
+ {
+ InThreadPtr *ptr = inthread_data;
+ ClientInfo *info = user_data;
+ DBusMessage *reply;
+
+ if (ptr && ptr->error) {
+ /* Client is still there, but query failed */
+ tracker_dbus_request_failed (info->request_id,
+ NULL,
+ &ptr->error,
+ NULL);
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ ptr->error->message);
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ g_error_free (ptr->error);
+ } else if (error) {
+ /* Client has disappeared */
+ tracker_dbus_request_failed (info->request_id,
+ NULL,
+ &error,
+ NULL);
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ error->message);
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ } else {
+ GStrv variable_names = ptr->variable_names;
+ DBusMessageIter iter, subiter;
+ guint i;
+
+ tracker_dbus_request_success (info->request_id,
+ NULL);
+ reply = dbus_message_new_method_return (info->call_message);
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &subiter);
+ for (i = 0; variable_names[i] != NULL; i++) {
+ gchar *variable_name = variable_names[i];
+ dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &variable_name);
+ }
+ dbus_message_iter_close_container (&iter, &subiter);
+
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ }
+
+ if (ptr) {
+ if (ptr->variable_names) {
+ g_strfreev (ptr->variable_names);
+ }
+ g_slice_free (InThreadPtr, ptr);
+ }
+ }
+
+ static void
+ update_callback (GError *error, gpointer user_data)
+ {
+ ClientInfo *info = user_data;
+ DBusMessage *reply;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ NULL,
+ &error,
+ NULL);
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ error->message);
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id, NULL);
+ reply = dbus_message_new_method_return (info->call_message);
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ }
+
+ static void
+ update_array_callback (GError *error, gpointer user_data)
+ {
+ ClientInfo *info = user_data;
+ DBusMessage *reply;
+
+ info->array_info.seen++;
+
+ if (!info->array_info.errors) {
+ info->array_info.errors = g_ptr_array_new ();
+ }
+
+ if (error) {
+ g_ptr_array_add (info->array_info.errors, g_error_copy (error));
+ } else {
+ g_ptr_array_add (info->array_info.errors, NULL);
+ }
+
+ if (info->array_info.seen == info->array_info.query_count) {
+ guint i;
+ DBusMessageIter iter, subiter;
+
+ tracker_dbus_request_success (info->request_id, NULL);
+ reply = dbus_message_new_method_return (info->call_message);
+
+ dbus_message_iter_init_append (reply, &iter);
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "ss", &subiter);
+
+ for (i = 0; i < info->array_info.errors->len; i++) {
+ GError *error = g_ptr_array_index (info->array_info.errors, i);
+ const gchar *str = "";
+ const gchar *message = "";
+
+ if (error) {
+ str = TRACKER_SPARQL_DBUS_ERROR;
+ message = error->message;
+ }
+
+ dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &str);
+ dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &message);
+
+ if (error) {
+ g_error_free (error);
+ }
+ }
+
+ g_ptr_array_free (info->array_info.errors, TRUE);
+
+ dbus_message_iter_close_container (&iter, &subiter);
+
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ client_info_destroy (info);
+ }
+ }
+
+ static void
+ marshal_hash_table_item (gpointer key,
+ gpointer value,
+ gpointer user_data)
+ {
+ DBusMessageIter *iter = user_data;
+ DBusMessageIter subiter;
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &subiter);
+ dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &key);
+ dbus_message_iter_append_basic (&subiter, DBUS_TYPE_STRING, &value);
+ dbus_message_iter_close_container (iter, &subiter);
+ }
+
+ static void
+ marshal_hash_table (DBusMessageIter *iter, GHashTable *hash)
+ {
+ DBusMessageIter subiter;
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &subiter);
+ g_hash_table_foreach (hash, marshal_hash_table_item, &subiter);
+ dbus_message_iter_close_container (iter, &subiter);
+ }
+
+ static void
+ update_blank_callback (GPtrArray *blank_nodes,
+ GError *error,
+ gpointer user_data)
+ {
+ ClientInfo *info;
+ DBusMessage *reply;
+ gint i, j;
+ /* Reply type is aaa{ss} */
+ DBusMessageIter iter;
+ DBusMessageIter subiter;
+ DBusMessageIter subsubiter;
+
+ info = user_data;
+
+ if (error) {
+ tracker_dbus_request_failed (info->request_id,
+ NULL,
+ &error,
+ NULL);
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ error->message);
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ return;
+ }
+
+ tracker_dbus_request_success (info->request_id, NULL);
+ reply = dbus_message_new_method_return (info->call_message);
+ dbus_message_iter_init_append (reply, &iter);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "aa{ss}", &subiter);
+ for (i = 0; i < blank_nodes->len; i++) {
+ GPtrArray *inner_array;
+
+ inner_array = g_ptr_array_index (blank_nodes, i);
+
+ dbus_message_iter_open_container (&subiter, DBUS_TYPE_ARRAY, "a{ss}", &subsubiter);
+ for (j = 0; j < inner_array->len; j++) {
+ GHashTable *hash = g_ptr_array_index (inner_array, j);
+
+ marshal_hash_table (&subsubiter, hash);
+ }
+ dbus_message_iter_close_container (&subiter, &subsubiter);
+ }
+ dbus_message_iter_close_container (&iter, &subiter);
+
+ dbus_connection_send (info->connection, reply, NULL);
+ dbus_message_unref (reply);
+ }
+
+ static gpointer
+ query_inthread (TrackerDBCursor *cursor,
+ GCancellable *cancellable,
+ GError *error,
+ gpointer user_data)
+ {
+ InThreadPtr *ptr;
+ ClientInfo *info;
+ GError *loop_error = NULL;
+ GOutputStream *unix_output_stream;
+ GOutputStream *output_stream;
+ GDataOutputStream *data_output_stream;
+ guint n_columns;
+ gint *column_sizes;
+ gint *column_offsets;
+ gint *column_types;
+ const gchar **column_data;
+ guint i;
+ GStrv variable_names = NULL;
+
+ ptr = g_slice_new0 (InThreadPtr);
+ info = user_data;
+ unix_output_stream = g_unix_output_stream_new (info->fd, TRUE);
+ output_stream = g_buffered_output_stream_new_sized (unix_output_stream,
+ TRACKER_STEROIDS_BUFFER_SIZE);
+ data_output_stream = g_data_output_stream_new (output_stream);
+ g_data_output_stream_set_byte_order (data_output_stream, G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+
+ if (error) {
+ g_object_unref (data_output_stream);
+ g_object_unref (output_stream);
+ g_object_unref (unix_output_stream);
+ ptr->error = g_error_copy (error);
+ return ptr;
+ }
+
+ n_columns = tracker_db_cursor_get_n_columns (cursor);
+
+ column_sizes = alloca (n_columns * sizeof (gint));
+ column_offsets = alloca (n_columns * sizeof (gint));
+ column_data = alloca (n_columns * sizeof (gchar*));
+ column_types = alloca (n_columns * sizeof (gchar*));
+
+ /* n_columns + 1 for NULL termination */
+ variable_names = g_new0 (gchar *, n_columns + 1);
+ for (i = 0; i < n_columns; i++) {
+ variable_names[i] = g_strdup (tracker_db_cursor_get_variable_name (cursor, i));
+ }
+
+ while (tracker_db_cursor_iter_next (cursor, cancellable, &loop_error)) {
+ gint i;
+ guint last_offset = -1;
+
+ if (loop_error != NULL) {
+ goto end_query_inthread;
+ }
+
+ for (i = 0; i < n_columns ; i++) {
+ const gchar *str;
+
+ str = tracker_db_cursor_get_string (cursor, i, NULL);
+
+ column_sizes[i] = str ? strlen (str) : 0;
+ column_data[i] = str;
+
+ /* Cast from enum to int */
+ column_types[i] = (gint) tracker_db_cursor_get_value_type (cursor, i);
+
+ last_offset += column_sizes[i] + 1;
+ column_offsets[i] = last_offset;
+ }
+
+ if (loop_error) {
+ goto end_query_inthread;
+ }
+
+ g_data_output_stream_put_int32 (data_output_stream,
+ n_columns,
+ NULL,
+ &loop_error);
+
+ if (loop_error) {
+ goto end_query_inthread;
+ }
+
+ for (i = 0; i < n_columns; i++) {
+ g_data_output_stream_put_int32 (data_output_stream,
+ column_types[i],
+ NULL,
+ &loop_error);
+ if (loop_error) {
+ goto end_query_inthread;
+ }
+ }
+
+ for (i = 0; i < n_columns; i++) {
+ g_data_output_stream_put_int32 (data_output_stream,
+ column_offsets[i],
+ NULL,
+ &loop_error);
+ if (loop_error) {
+ goto end_query_inthread;
+ }
+ }
+
+ for (i = 0; i < n_columns; i++) {
+ g_data_output_stream_put_string (data_output_stream,
+ column_data[i] ? column_data[i] : "",
+ NULL,
+ &loop_error);
+
+ if (loop_error) {
+ goto end_query_inthread;
+ }
+
+ g_data_output_stream_put_byte (data_output_stream,
+ 0,
+ NULL,
+ &loop_error);
+
+ if (loop_error) {
+ goto end_query_inthread;
+ }
+ }
+ }
+
+ end_query_inthread:
+ /* Will force flushing */
+ g_object_unref (data_output_stream);
+ g_object_unref (output_stream);
+ g_object_unref (unix_output_stream);
+
+ if (loop_error) {
+ ptr->error = loop_error;
+ if (variable_names) {
+ g_strfreev (variable_names);
+ }
+ } else {
+ ptr->variable_names = variable_names;
+ }
+
+ return ptr;
+ }
+#endif
+
+ public void query (string query, UnixOutputStream output_stream) throws Error {
+#if 0
+ ClientInfo *info;
+ guint request_id;
+ const gchar *sender;
+ const gchar *expected_signature;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ gchar *query;
+ int fd;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ expected_signature = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UNIX_FD_AS_STRING;
+
+ if (g_strcmp0 (dbus_message_get_signature (message), expected_signature)) {
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s()",
+ __FUNCTION__);
+
+ reply = dbus_message_new_error_printf (message,
+ DBUS_ERROR_UNKNOWN_METHOD,
+ UNKNOWN_METHOD_MESSAGE,
+ "Query",
+ dbus_message_get_signature (message),
+ dbus_message_get_interface (message),
+ expected_signature);
+ dbus_connection_send (connection, reply, NULL);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ UNKNOWN_METHOD_MESSAGE,
+ "Query",
+ dbus_message_get_signature (message),
+ dbus_message_get_interface (message),
+ expected_signature);
+
+ dbus_message_unref (reply);
+
+ return;
+ }
+
+ dbus_error_init (&dbus_error);
+
+ dbus_message_get_args (message,
+ &dbus_error,
+ DBUS_TYPE_STRING, &query,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s()",
+ __FUNCTION__);
+
+ reply = dbus_message_new_error (message, dbus_error.name, dbus_error.message);
+ dbus_connection_send (connection, reply, NULL);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ dbus_error.message);
+
+ dbus_message_unref (reply);
+ dbus_error_free (&dbus_error);
+
+ return;
+ }
+
+ info = g_slice_new0 (ClientInfo);
+ info->connection = dbus_connection_ref (connection);
+ info->call_message = dbus_message_ref (message);
+ info->request_id = request_id;
+ info->fd = fd;
+
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s(query:'%s')",
+ __FUNCTION__,
+ query);
+
+ sender = dbus_message_get_sender (message);
+
+ tracker_store_sparql_query (query,
+ TRACKER_STORE_PRIORITY_HIGH,
+ query_inthread,
+ query_callback,
+ sender,
+ info,
+ client_info_destroy);
+#endif
+ }
+
+ public async void update (BusName sender, UnixInputStream input_stream, Cancellable? cancellable) throws Error {
+#if 0
+ DBusError dbus_error;
+ ClientInfo *info;
+ GError *error = NULL;
+ guint request_id;
+ const gchar *sender;
+ gchar *query;
+ int fd;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s(fd:%d)",
+ __FUNCTION__,
+ fd);
+
+ info = g_slice_new0 (ClientInfo);
+ info->connection = dbus_connection_ref (connection);
+ info->call_message = dbus_message_ref (message);
+ info->request_id = request_id;
+ info->fd = fd;
+
+ sender = dbus_message_get_sender (message);
+#endif
+
+ size_t bytes_read;
+
+ var data_input_stream = new DataInputStream (input_stream);
+ data_input_stream.set_buffer_size (BUFFER_SIZE);
+ data_input_stream.set_byte_order (DataStreamByteOrder.HOST_ENDIAN);
+
+ int query_size = data_input_stream.read_int32 (null);
+
+ /* We malloc one more char to ensure string is 0 terminated */
+ uint8[] query = new uint8[query_size + 1];
+
+ data_input_stream.read_all (query[0:query_size], out bytes_read, null);
+
+ data_input_stream = null;
+ input_stream = null;
+
+#if 0
+ tracker_dbus_request_debug (request_id,
+ NULL,
+ "query: '%s'",
+ query);
+
+ if (update_blank) {
+ tracker_store_sparql_update_blank (query,
+ TRACKER_STORE_PRIORITY_HIGH,
+ update_blank_callback,
+ sender,
+ info,
+ client_info_destroy);
+ } else {
+#endif
+ yield Tracker.Store.sparql_update ((string) query, /*batch ? TRACKER_STORE_PRIORITY_LOW :*/ Tracker.Store.Priority.HIGH, sender);
+#if 0
+ }
+#endif
+ }
+
+
+#if 0
+ static void
+ steroids_update_array (TrackerSteroids *steroids,
+ DBusConnection *connection,
+ DBusMessage *message,
+ gboolean batch)
+ {
+ DBusError dbus_error;
+ ClientInfo *info;
+ GInputStream *input_stream;
+ GDataInputStream *data_input_stream;
+ GError *error = NULL;
+ guint request_id;
+ const gchar *sender;
+ int i;
+ DBusMessage *reply;
+ int fd;
+ gchar **query_array;
+
+ request_id = tracker_dbus_get_next_request_id ();
+
+ if (g_strcmp0 (dbus_message_get_signature (message), DBUS_TYPE_UNIX_FD_AS_STRING)) {
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s()",
+ __FUNCTION__);
+
+ reply = dbus_message_new_error_printf (message,
+ DBUS_ERROR_UNKNOWN_METHOD,
+ UNKNOWN_METHOD_MESSAGE,
+ "Update",
+ dbus_message_get_signature (message),
+ dbus_message_get_interface (message),
+ DBUS_TYPE_UNIX_FD_AS_STRING);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ UNKNOWN_METHOD_MESSAGE,
+ "Update",
+ dbus_message_get_signature (message),
+ dbus_message_get_interface (message),
+ DBUS_TYPE_UNIX_FD_AS_STRING);
+
+ return;
+ }
+
+ dbus_error_init (&dbus_error);
+
+ dbus_message_get_args (message,
+ &dbus_error,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s()",
+ __FUNCTION__);
+
+ reply = dbus_message_new_error (message, dbus_error.name, dbus_error.message);
+ dbus_connection_send (connection, reply, NULL);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ dbus_error.message);
+
+ dbus_message_unref (reply);
+ dbus_error_free (&dbus_error);
+
+ return;
+ }
+
+ tracker_dbus_request_new (request_id,
+ NULL,
+ "%s(fd:%d)",
+ __FUNCTION__,
+ fd);
+
+ info = g_slice_new0 (ClientInfo);
+ info->connection = dbus_connection_ref (connection);
+ info->call_message = dbus_message_ref (message);
+ info->request_id = request_id;
+ info->fd = fd;
+
+ sender = dbus_message_get_sender (message);
+
+ input_stream = g_unix_input_stream_new (info->fd, TRUE);
+ data_input_stream = g_data_input_stream_new (input_stream);
+ g_data_input_stream_set_byte_order (data_input_stream, G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
+ g_buffered_input_stream_set_buffer_size (G_BUFFERED_INPUT_STREAM (data_input_stream),
+ TRACKER_STEROIDS_BUFFER_SIZE);
+
+ info->array_info.query_count = g_data_input_stream_read_uint32 (data_input_stream,
+ NULL,
+ &error);
+
+ if (error) {
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ error->message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ error->message);
+
+ g_object_unref (data_input_stream);
+ g_object_unref (input_stream);
+ g_error_free (error);
+ client_info_destroy (info);
+
+ return;
+ }
+
+ info->array_info.seen = 0;
+ query_array = g_new0 (gchar*, info->array_info.query_count + 1);
+
+ for (i = 0; i < info->array_info.query_count; i++) {
+ gsize bytes_read;
+ int query_size;
+
+ query_size = g_data_input_stream_read_int32 (data_input_stream,
+ NULL,
+ &error);
+
+ if (error) {
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ error->message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ error->message);
+
+ g_strfreev (query_array);
+ g_object_unref (data_input_stream);
+ g_object_unref (input_stream);
+ g_error_free (error);
+ client_info_destroy (info);
+
+ return;
+ }
+
+ /* We malloc one more char to ensure string is 0 terminated */
+ query_array[i] = g_malloc0 ((1 + query_size) * sizeof (char));
+
+ g_input_stream_read_all (input_stream,
+ query_array[i],
+ query_size,
+ &bytes_read,
+ NULL,
+ &error);
+
+ if (error) {
+ reply = dbus_message_new_error (info->call_message,
+ TRACKER_SPARQL_DBUS_ERROR,
+ error->message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ tracker_dbus_request_failed (request_id,
+ NULL,
+ NULL,
+ error->message);
+
+ g_strfreev (query_array);
+ g_object_unref (data_input_stream);
+ g_object_unref (input_stream);
+ g_error_free (error);
+ client_info_destroy (info);
+
+ return;
+ }
+
+ }
+
+ g_object_unref (data_input_stream);
+ g_object_unref (input_stream);
+
+ for (i = 0; query_array[i] != NULL; i++) {
+
+ tracker_dbus_request_debug (request_id,
+ NULL,
+ "query: '%s'",
+ query_array[i]);
+
+ tracker_store_sparql_update (query_array[i],
+ batch ? TRACKER_STORE_PRIORITY_LOW : TRACKER_STORE_PRIORITY_HIGH,
+ update_array_callback,
+ sender,
+ info,
+ NULL);
+ }
+
+ g_strfreev (query_array);
+ }
+
+ DBusHandlerResult
+ tracker_steroids_connection_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+ {
+ TrackerSteroids *steroids;
+
+ g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+ if (g_strcmp0 (TRACKER_STEROIDS_PATH, dbus_message_get_path (message))) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (g_strcmp0 (TRACKER_STEROIDS_INTERFACE, dbus_message_get_interface (message))) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ /* Only check if the user_data is our TrackerSteroids AFTER having checked that
+ * the message matches expected path and interface. */
+ steroids = user_data;
+ g_return_val_if_fail (TRACKER_IS_STEROIDS (steroids), DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+ if (!g_strcmp0 ("Query", dbus_message_get_member (message))) {
+ steroids_query (steroids, connection, message);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (!g_strcmp0 ("UpdateArray", dbus_message_get_member (message))) {
+ steroids_update_array (steroids, connection, message, FALSE);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (!g_strcmp0 ("Update", dbus_message_get_member (message))) {
+ steroids_update (steroids, connection, message, FALSE, FALSE);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (!g_strcmp0 ("UpdateBlank", dbus_message_get_member (message))) {
+ steroids_update (steroids, connection, message, FALSE, TRUE);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (!g_strcmp0 ("BatchUpdate", dbus_message_get_member (message))) {
+ steroids_update (steroids, connection, message, TRUE, FALSE);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (!g_strcmp0 ("BatchUpdateArray", dbus_message_get_member (message))) {
+ steroids_update_array (steroids, connection, message, TRUE);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+#endif
+}
diff --git a/src/tracker-store/tracker-store.vala b/src/tracker-store/tracker-store.vala
new file mode 100644
index 0000000..b65da4a
--- /dev/null
+++ b/src/tracker-store/tracker-store.vala
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2009, Nokia <ivan frade nokia com>
+ *
+ * This library 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 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 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: Philip Van Hoof <philip codeminded be>
+ */
+
+class Tracker.Store {
+ const int MAX_CONCURRENT_QUERIES = 2;
+
+ const int MAX_TASK_TIME = 30;
+
+ static bool start_log;
+ static Queue<Task> query_queues[2 /* TRACKER_STORE_N_PRIORITIES */];
+ static Queue<Task> update_queues[2 /* TRACKER_STORE_N_PRIORITIES */];
+ static int n_queries_running;
+ static bool update_running;
+ static ThreadPool<Task> update_pool;
+ static ThreadPool<Task> query_pool;
+ //GSList *running_tasks;
+ static int max_task_time;
+ static bool active;
+ static DestroyNotify active_callback;
+ static void* active_user_data;
+
+ public enum Priority {
+ HIGH,
+ LOW,
+ TURTLE,
+ N_PRIORITIES
+ }
+
+ enum TaskType {
+ QUERY,
+ UPDATE,
+ UPDATE_BLANK,
+ TURTLE,
+ }
+
+ abstract class Task {
+ public TaskType type;
+ public string client_id;
+ public Error error;
+ public SourceFunc callback;
+ }
+
+ class QueryTask : Task {
+ public string query;
+ public Cancellable cancellable;
+ public void* thread_data;
+ public uint watchdog_id;
+ //TrackerStoreSparqlQueryInThread in_thread;
+ }
+
+ class UpdateTask : Task {
+ public string query;
+ //GPtrArray *blank_nodes;
+ public Priority priority;
+ }
+
+ class TurtleTask : Task {
+ public string path;
+ }
+
+#if 0
+ struct SetActiveDelegate {
+ GDestroyNotify callback;
+ gpointer user_data;
+ }
+
+ static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
+
+ /* cpu used for mainloop thread and main update/query thread */
+ static int main_cpu;
+
+ static void
+ private_free (gpointer data)
+ {
+ TrackerStorePrivate *private = data;
+ gint i;
+
+ for (i = 0; i < N_PRIORITIES; i++) {
+ g_queue_free (query_queues[i]);
+ g_queue_free (update_queues[i]);
+ }
+ g_free (private);
+ }
+
+ static void
+ store_task_free (TrackerStoreTask *task)
+ {
+ if (task.type == TaskType.TURTLE) {
+ g_free (task.data.turtle.path);
+ } else if (task.type == TaskType.QUERY) {
+ g_free (task.data.query.query);
+ if (task.data.query.watchdog_id) {
+ g_source_remove (task.data.query.watchdog_id);
+ }
+ if (task.data.query.cancellable) {
+ g_object_unref (task.data.query.cancellable);
+ }
+ } else {
+ g_free (task.data.update.query);
+ }
+
+ g_free (task.client_id);
+ g_slice_free (TrackerStoreTask, task);
+ }
+
+ bool watchdog_cb (gpointer user_data) {
+ TrackerStoreTask *task = user_data;
+
+ g_cancellable_cancel (task.data.query.cancellable);
+
+ return FALSE;
+ }
+#endif
+
+ static void sched () {
+ Queue<Task> queue;
+ Task task = null;
+
+ if (!active) {
+ return;
+ }
+
+ while (n_queries_running < MAX_CONCURRENT_QUERIES) {
+ for (int i = 0; i < Priority.N_PRIORITIES; i++) {
+ task = query_queues[i].pop_head ();
+ if (task != null) {
+ break;
+ }
+ }
+ if (task == null) {
+ /* no pending query */
+ break;
+ }
+
+ //running_tasks = g_slist_prepend (running_tasks, task);
+
+ if (max_task_time != 0) {
+ //task.watchdog_id = Timeout.add_seconds (max_task_time, watchdog_cb, task);
+ }
+
+ n_queries_running++;
+ query_pool.push (task);
+ }
+
+ if (!update_running) {
+ for (int i = 0; i < Priority.N_PRIORITIES; i++) {
+ task = update_queues[i].pop_head ();
+ if (task != null) {
+ break;
+ }
+ }
+ if (task != null) {
+ update_running = true;
+ update_pool.push (task);
+ }
+ }
+ }
+
+ static bool start_timer_or_not (Task task) {
+ bool result;
+
+ switch (task.type) {
+ case TaskType.UPDATE:
+ case TaskType.UPDATE_BLANK:
+ result = !(((UpdateTask) task).priority == Priority.LOW && update_queues[Priority.LOW].get_length () > 0);
+ break;
+ case TaskType.TURTLE:
+ result = update_queues[Priority.TURTLE].get_length () == 0;
+ break;
+ case TaskType.QUERY:
+ default:
+ result = false;
+ break;
+ }
+
+ return result;
+ }
+
+ static bool task_finish_cb (Task task) {
+ if (task.type == TaskType.QUERY) {
+#if 0
+ var query_task = (QueryTask) task;
+
+ if (task.error == null) {
+ g_cancellable_set_error_if_cancelled (task.data.query.cancellable, &task.error);
+ }
+
+ task.callback ();
+ task.error = null;
+
+ running_tasks = g_slist_remove (running_tasks, task);
+ n_queries_running--;
+#endif
+ } else if (task.type == TaskType.UPDATE) {
+ var update_task = (UpdateTask) task;
+
+ if (task.error == null) {
+ Tracker.Data.notify_transaction (start_timer_or_not (task));
+ }
+
+ task.callback ();
+ task.error = null;
+
+ update_running = false;
+ } else if (task.type == TaskType.UPDATE_BLANK) {
+ var update_task = (UpdateTask) task;
+
+ if (task.error == null) {
+ Tracker.Data.notify_transaction (start_timer_or_not (task));
+ }
+
+#if 0
+ if (!task.data.update.blank_nodes) {
+ /* Create empty GPtrArray for dbus-glib to be happy */
+ task.data.update.blank_nodes = g_ptr_array_new ();
+ }
+#endif
+
+ task.callback ();
+
+#if 0
+ if (task.data.update.blank_nodes) {
+ for (int i = 0; i < task.data.update.blank_nodes->len; i++) {
+ g_ptr_array_foreach (task.data.update.blank_nodes->pdata[i], (GFunc) g_hash_table_unref, NULL);
+ g_ptr_array_free (task.data.update.blank_nodes->pdata[i], TRUE);
+ }
+ g_ptr_array_free (task.data.update.blank_nodes, TRUE);
+ }
+#endif
+
+ task.error = null;
+
+ update_running = false;
+ } else if (task.type == TaskType.TURTLE) {
+ var turtle_task = (TurtleTask) task;
+
+ if (task.error == null) {
+ Tracker.Data.notify_transaction (start_timer_or_not (task));
+ }
+
+ task.callback ();
+ task.error = null;
+
+ update_running = false;
+ }
+
+#if 0
+ if (n_queries_running == 0 &&
+ !update_running &&
+ active_callback != null)
+ {
+ active_callback (active_user_data);
+ active_callback = null;
+ }
+#endif
+
+ sched ();
+
+ return false;
+ }
+
+ static void pool_dispatch_cb (Task task) {
+#if 0
+ /* special task, only ever sent to main pool */
+ if (GPOINTER_TO_INT (data) == 1) {
+ if (g_getenv ("TRACKER_STORE_DISABLE_CPU_AFFINITY") == NULL) {
+ cpu_set_t cpuset;
+ CPU_ZERO (&cpuset);
+ CPU_SET (main_cpu, &cpuset);
+
+ /* avoid cpu hopping which can lead to significantly worse performance */
+ pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
+ return;
+ }
+ }
+#endif
+
+ try {
+ if (task.type == TaskType.QUERY) {
+ var query_task = (QueryTask) task;
+
+ var cursor = Tracker.Data.query_sparql_cursor (query_task.query);
+
+ //task.data.query.thread_data = task.callback.query.in_thread (cursor, task.data.query.cancellable, task.error, task.user_data);
+ } else if (task.type == TaskType.UPDATE) {
+ var update_task = (UpdateTask) task;
+
+ Tracker.Data.update_sparql (update_task.query);
+ } else if (task.type == TaskType.UPDATE_BLANK) {
+ var update_task = (UpdateTask) task;
+
+ /*update_task.blank_nodes =*/ Tracker.Data.update_sparql_blank (update_task.query);
+ } else if (task.type == TaskType.TURTLE) {
+ var turtle_task = (TurtleTask) task;
+
+ var file = File.new_for_path (turtle_task.path);
+
+ #if 0
+ tracker_events_freeze ();
+ Tracker.Data.load_turtle_file (file);
+ tracker_events_reset_pending ();
+ #endif
+ }
+ } catch (Error e) {
+ task.error = e;
+ }
+
+ Idle.add (() => {
+ task_finish_cb (task);
+ return false;
+ });
+ }
+
+ public static void init () {
+#if 0
+ TrackerStorePrivate *private;
+ const char *tmp;
+ cpu_set_t cpuset;
+
+ private = g_new0 (TrackerStorePrivate, 1);
+#endif
+
+ /*if ((tmp = g_getenv("TRACKER_STORE_MAX_TASK_TIME")) != NULL) {
+ max_task_time = atoi (tmp);
+ } else*/ {
+ max_task_time = MAX_TASK_TIME;
+ }
+
+ for (int i = 0; i < Priority.N_PRIORITIES; i++) {
+ query_queues[i] = new Queue<Task> ();
+ update_queues[i] = new Queue<Task> ();
+ }
+
+ update_pool = new ThreadPool<Task> (pool_dispatch_cb, 1, true);
+ query_pool = new ThreadPool<Task> (pool_dispatch_cb, MAX_CONCURRENT_QUERIES, true);
+
+#if 0
+ /* as the following settings are global for unknown reasons,
+ let's use the same settings as gio, otherwise the used settings
+ are rather random */
+ g_thread_pool_set_max_idle_time (15 * 1000);
+ g_thread_pool_set_max_unused_threads (2);
+
+ if (g_getenv ("TRACKER_STORE_DISABLE_CPU_AFFINITY") == NULL) {
+ sched_getcpu ();
+ main_cpu = sched_getcpu ();
+ CPU_ZERO (&cpuset);
+ CPU_SET (main_cpu, &cpuset);
+
+ /* avoid cpu hopping which can lead to significantly worse performance */
+ pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
+ /* lock main update/query thread to same cpu to improve overall performance
+ main loop thread is essentially idle during query execution */
+ g_thread_pool_push (update_pool, GINT_TO_POINTER (1), NULL);
+ }
+
+ g_static_private_set (&private_key,
+ private,
+ private_free);
+#endif
+ }
+
+ public static void shutdown () {
+#if 0
+ TrackerStorePrivate *private;
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ g_thread_pool_free (query_pool, FALSE, TRUE);
+ g_thread_pool_free (update_pool, FALSE, TRUE);
+
+ g_static_private_set (&private_key, NULL, NULL);
+#endif
+ }
+
+#if 0
+ public void sparql_query (string sparql,
+ TrackerStorePriority priority,
+ TrackerStoreSparqlQueryInThread in_thread,
+ TrackerStoreSparqlQueryCallback callback,
+ string client_id,
+ gpointer user_data,
+ GDestroyNotify destroy)
+ {
+ TrackerStorePrivate *private;
+ TrackerStoreTask *task;
+
+ g_return_if_fail (sparql != NULL);
+ g_return_if_fail (in_thread != NULL);
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ task = g_slice_new0 (TrackerStoreTask);
+ task.type = TaskType.QUERY;
+ task.data.query.query = g_strdup (sparql);
+ task.data.query.cancellable = g_cancellable_new ();
+ task.user_data = user_data;
+ task.callback.query.query_callback = callback;
+ task.callback.query.in_thread = in_thread;
+ task.destroy = destroy;
+ task.client_id = g_strdup (client_id);
+
+ g_queue_push_tail (query_queues[priority], task);
+
+ sched (private);
+ }
+#endif
+
+ public static async void sparql_update (string sparql, Priority priority, string client_id) {
+ var task = new UpdateTask ();
+ task.type = TaskType.UPDATE;
+ task.query = sparql;
+ task.priority = priority;
+ task.callback = sparql_update.callback;
+ task.client_id = client_id;
+
+ update_queues[priority].push_tail (task);
+
+ sched ();
+
+ yield;
+ }
+
+#if 0
+ public void sparql_update_blank (string sparql,
+ TrackerStorePriority priority,
+ TrackerStoreSparqlUpdateBlankCallback callback,
+ string client_id,
+ gpointer user_data,
+ GDestroyNotify destroy)
+ {
+ TrackerStorePrivate *private;
+ TrackerStoreTask *task;
+
+ g_return_if_fail (sparql != NULL);
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ task = g_slice_new0 (TrackerStoreTask);
+ task.type = TaskType.UPDATE_BLANK;
+ task.data.update.query = g_strdup (sparql);
+ task.user_data = user_data;
+ task.callback.update_blank_callback = callback;
+ task.destroy = destroy;
+ task.client_id = g_strdup (client_id);
+
+ g_queue_push_tail (update_queues[priority], task);
+
+ sched (private);
+ }
+
+ public void queue_turtle_import (File file, owned TrackerStoreTurtleCallback callback, string client_id)
+ {
+ TrackerStorePrivate *private;
+ TrackerStoreTask *task;
+
+ g_return_if_fail (G_IS_FILE (file));
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ task = g_slice_new0 (TrackerStoreTask);
+ task.type = TaskType.TURTLE;
+ task.data.turtle.path = g_file_get_path (file);
+ task.user_data = user_data;
+ task.callback.update_callback = callback;
+ task.destroy = destroy;
+ task.client_id = g_strdup (client_id);
+
+ g_queue_push_tail (update_queues[TRACKER_STORE_PRIORITY_TURTLE], task);
+
+ sched (private);
+ }
+
+ uint get_queue_size () {
+ TrackerStorePrivate *private;
+ gint i;
+ guint result = 0;
+
+ private = g_static_private_get (&private_key);
+ g_return_val_if_fail (private != NULL, 0);
+
+ for (i = 0; i < TRACKER_STORE_N_PRIORITIES; i++) {
+ result += g_queue_get_length (query_queues[i]);
+ result += g_queue_get_length (update_queues[i]);
+ }
+ return result;
+ }
+
+ void unreg_task (Task task, Error error) {
+ if (task.type == TaskType.QUERY) {
+ task.callback.query.query_callback (NULL, error, task.user_data);
+ } else if (task.type == TaskType.UPDATE) {
+ task.callback.update_callback (error, task.user_data);
+ } else if (task.type == TaskType.UPDATE_BLANK) {
+ task.callback.update_blank_callback (NULL, error, task.user_data);
+ } else if (task.type == TaskType.TURTLE) {
+ task.callback.turtle_callback (error, task.user_data);
+ }
+
+ if (task.destroy) {
+ task.destroy (task.user_data);
+ }
+
+ store_task_free (task);
+ }
+
+ public void unreg_batches (string client_id) {
+ TrackerStorePrivate *private;
+ static GError *error = NULL;
+ GList *list, *cur;
+ GSList *running;
+ GQueue *queue;
+ gint i;
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ for (running = running_tasks; running; running = running->next) {
+ TrackerStoreTask *task;
+
+ task = running->data;
+
+ if (task.data.query.cancellable &&
+ g_strcmp0 (task.client_id, client_id) == 0) {
+ g_cancellable_cancel (task.data.query.cancellable);
+ }
+ }
+
+ for (i = 0; i < TRACKER_STORE_N_PRIORITIES; i++) {
+ queue = query_queues[i];
+ list = queue->head;
+ while (list) {
+ TrackerStoreTask *task;
+
+ cur = list;
+ list = list->next;
+ task = cur->data;
+
+ if (task && g_strcmp0 (task.client_id, client_id) == 0) {
+ g_queue_delete_link (queue, cur);
+
+ if (!error) {
+ g_set_error (&error, TRACKER_DBUS_ERROR, 0,
+ "Client disappeared");
+ }
+
+ unreg_task (task, error);
+ }
+ }
+
+ queue = update_queues[i];
+ list = queue->head;
+ while (list) {
+ TrackerStoreTask *task;
+
+ cur = list;
+ list = list->next;
+ task = cur->data;
+
+ if (task && g_strcmp0 (task.client_id, client_id) == 0) {
+ g_queue_delete_link (queue, cur);
+
+ if (!error) {
+ g_set_error (&error, TRACKER_DBUS_ERROR, 0,
+ "Client disappeared");
+ }
+
+ unreg_task (task, error);
+ }
+ }
+ }
+
+ if (error) {
+ g_clear_error (&error);
+ }
+
+ sched (private);
+ }
+
+ bool active_cb_in_idle (gpointer user_data)
+ {
+ SetActiveDelegate *data = user_data;
+
+ data->callback (data->user_data);
+ g_free (data);
+
+ return FALSE;
+ }
+#endif
+
+ public static void set_active (bool active, DestroyNotify? callback) {
+ Tracker.Store.active = active;
+
+ if (active == false &&
+ n_queries_running == 0 &&
+ !update_running &&
+ callback != null)
+ {
+#if 0
+ SetActiveDelegate *data = g_new0 (SetActiveDelegate, 1);
+
+ data->callback = callback;
+ data->user_data = user_data;
+ g_idle_add (active_cb_in_idle, data);
+#endif
+
+ active_callback = null;
+ } else {
+ active_callback = callback;
+#if 0
+ active_user_data = user_data;
+#endif
+ }
+
+ if (active) {
+ sched ();
+ }
+ }
+}
diff --git a/src/tracker-store/tracker-writeback.c b/src/tracker-store/tracker-writeback.c
index bdd02d5..f26a9c2 100644
--- a/src/tracker-store/tracker-writeback.c
+++ b/src/tracker-store/tracker-writeback.c
@@ -20,6 +20,8 @@
* Philip Van Hoof <philip codeminded be>
*/
+#if 0
+
#include "config.h"
#include <libtracker-data/tracker-data.h>
@@ -216,3 +218,5 @@ tracker_writeback_shutdown (void)
free_private (private);
private = NULL;
}
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]