From 62ec35a733aee0a7ce7a820027e8507183ac212d Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Wed, 21 Oct 2009 15:23:26 +0200 Subject: [PATCH] Load beagle/tracker at runtime Dynamically load beagle and tracker client libraries on demand if available. This allows more flexibility for packagers and users. See bug 589345 for details. --- configure.in | 62 --------- libnautilus-private/Makefile.am | 20 +--- .../nautilus-search-engine-beagle.c | 132 ++++++++++++++++++- .../nautilus-search-engine-tracker.c | 142 ++++++++++++++++---- libnautilus-private/nautilus-search-engine.c | 4 - 5 files changed, 248 insertions(+), 112 deletions(-) diff --git a/configure.in b/configure.in index 45f0b26..866e8f3 100644 --- a/configure.in +++ b/configure.in @@ -195,66 +195,6 @@ if test "x$enable_xmp" != "xno"; then fi dnl ========================================================================== -dnl search implementations -dnl **************************** - -AM_CONDITIONAL(HAVE_TRACKER, false) - -dnl libtracker checking - -AC_ARG_ENABLE(tracker, - AC_HELP_STRING([--disable-tracker], - [build without tracker support])) -msg_tracker=no -if test "x$enable_tracker" != "xno"; then - PKG_CHECK_MODULES(TRACKER, tracker-client-0.7, [ - AM_CONDITIONAL(HAVE_TRACKER, true) - AC_DEFINE(HAVE_TRACKER, 1, [Define to enable tracker support]) - AC_DEFINE(HAVE_TRACKER_0_7, 1, [Define to enable tracker support]) - ] - msg_tracker=yes, - [ - PKG_CHECK_MODULES(TRACKER, tracker >= tracker_minver, [ - AM_CONDITIONAL(HAVE_TRACKER, true) - AC_DEFINE(HAVE_TRACKER, 1, [Define to enable tracker support]) - ] - msg_tracker=yes, - [AM_CONDITIONAL(HAVE_TRACKER, false)]) - ]) - AC_SUBST(TRACKER_CFLAGS) - AC_SUBST(TRACKER_LIBS) -fi - -dnl ========================================================================== - - -AM_CONDITIONAL(HAVE_BEAGLE, false) - -dnl libbeagle checking - -AC_ARG_ENABLE(beagle, - AC_HELP_STRING([--disable-beagle], - [build without beagle support])) -msg_beagle=no -if test "x$enable_beagle" != "xno"; then - BEAGLE_PKGCONFIG= - if $PKG_CONFIG --exists libbeagle-1.0; then - BEAGLE_PKGCONFIG=libbeagle-1.0 - else - BEAGLE_PKGCONFIG=libbeagle-0.0 - fi - - PKG_CHECK_MODULES(BEAGLE, $BEAGLE_PKGCONFIG >= beagle_minver, [ - AM_CONDITIONAL(HAVE_BEAGLE, true) - AC_DEFINE(HAVE_BEAGLE, 1, [Define to enable beagle support]) - ] - msg_beagle=yes, - [AM_CONDITIONAL(HAVE_BEAGLE, false)]) - AC_SUBST(BEAGLE_CFLAGS) - AC_SUBST(BEAGLE_LIBS) -fi - -dnl ========================================================================== dnl **************************** dnl *** Check for libselinux *** @@ -470,8 +410,6 @@ nautilus-$VERSION: prefix: ${prefix} source code location: ${srcdir} compiler: ${CC} - tracker support: $msg_tracker - beagle support: $msg_beagle xmp support: $msg_xmp PackageKit support: $msg_packagekit diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index e831d43..0f817fc 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -154,6 +154,10 @@ libnautilus_private_la_SOURCES = \ nautilus-search-engine.h \ nautilus-search-engine-simple.c \ nautilus-search-engine-simple.h \ + nautilus-search-engine-beagle.c \ + nautilus-search-engine-beagle.h \ + nautilus-search-engine-tracker.c \ + nautilus-search-engine-tracker.h \ nautilus-sidebar-provider.c \ nautilus-sidebar-provider.h \ nautilus-sidebar.c \ @@ -195,22 +199,6 @@ libnautilus_private_la_SOURCES = \ nautilus-window-slot-info.h \ $(NULL) -BEAGLE_SOURCES = \ - nautilus-search-engine-beagle.c \ - nautilus-search-engine-beagle.h - -if HAVE_BEAGLE -libnautilus_private_la_SOURCES += $(BEAGLE_SOURCES) -endif - -TRACKER_SOURCES = \ - nautilus-search-engine-tracker.c \ - nautilus-search-engine-tracker.h - -if HAVE_TRACKER -libnautilus_private_la_SOURCES += $(TRACKER_SOURCES) -endif - $(lib_LTLIBRARIES): $(dependency_static_libs) nautilus-marshal.h: nautilus-marshal.list $(GLIB_GENMARSHAL) diff --git a/libnautilus-private/nautilus-search-engine-beagle.c b/libnautilus-private/nautilus-search-engine-beagle.c index 3ab6507..930923f 100644 --- a/libnautilus-private/nautilus-search-engine-beagle.c +++ b/libnautilus-private/nautilus-search-engine-beagle.c @@ -23,10 +23,20 @@ #include #include "nautilus-search-engine-beagle.h" -#include #include #include +#include + +typedef struct _BeagleHit BeagleHit; +typedef struct _BeagleQuery BeagleQuery; +typedef struct _BeagleClient BeagleClient; +typedef struct _BeagleRequest BeagleRequest; +typedef struct _BeagleFinishedResponse BeagleFinishedResponse; +typedef struct _BeagleHitsAddedResponse BeagleHitsAddedResponse; +typedef struct _BeagleQueryPartProperty BeagleQueryPartProperty; +typedef struct _BeagleQueryPart BeagleQueryPart; +typedef struct _BeagleHitsSubtractedResponse BeagleHitsSubtractedResponse; struct NautilusSearchEngineBeagleDetails { BeagleClient *client; @@ -37,6 +47,121 @@ struct NautilusSearchEngineBeagleDetails { gboolean query_finished; }; +/* We dlopen() all the following from libbeagle at runtime */ +#define BEAGLE_HIT(x) ((BeagleHit *)(x)) +#define BEAGLE_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), beagle_request_get_type(), BeagleRequest)) +#define BEAGLE_QUERY_PART(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), beagle_query_part_get_type(), BeagleQueryPart)) + +typedef enum { + BEAGLE_QUERY_PART_LOGIC_REQUIRED = 1, + BEAGLE_QUERY_PART_LOGIC_PROHIBITED = 2 +} BeagleQueryPartLogic; + +typedef enum { + BEAGLE_PROPERTY_TYPE_UNKNOWN = 0, + BEAGLE_PROPERTY_TYPE_TEXT = 1, + BEAGLE_PROPERTY_TYPE_KEYWORD = 2, + BEAGLE_PROPERTY_TYPE_DATE = 3, + BEAGLE_PROPERTY_TYPE_LAST = 4 +} BeaglePropertyType; + +/* *static* wrapper function pointers */ +static gboolean (*beagle_client_send_request_async) (BeagleClient *client, + BeagleRequest *request, + GError **err) = NULL; +static G_CONST_RETURN char *(*beagle_hit_get_uri) (BeagleHit *hit) = NULL; +static GSList *(*beagle_hits_added_response_get_hits) (BeagleHitsAddedResponse *response) = NULL; +static BeagleQuery *(*beagle_query_new) (void) = NULL; +static void (*beagle_query_add_text) (BeagleQuery *query, + const char *str) = NULL; +static BeagleQueryPartProperty *(*beagle_query_part_property_new) (void) = NULL; +static void (*beagle_query_part_set_logic) (BeagleQueryPart *part, + BeagleQueryPartLogic logic) = NULL; +static void (*beagle_query_part_property_set_key) (BeagleQueryPartProperty *part, + const char *key) = NULL; +static void (*beagle_query_part_property_set_value) (BeagleQueryPartProperty *part, + const char * value) = NULL; +static void (*beagle_query_part_property_set_property_type) (BeagleQueryPartProperty *part, + BeaglePropertyType prop_type) = NULL; +static void (*beagle_query_add_part) (BeagleQuery *query, + BeagleQueryPart *part) = NULL; +static GType (*beagle_request_get_type) (void) = NULL; +static GType (*beagle_query_part_get_type) (void) = NULL; +static gboolean (*beagle_util_daemon_is_running) (void) = NULL; +static BeagleClient *(*beagle_client_new_real) (const char *client_name) = NULL; +static void (*beagle_query_set_max_hits) (BeagleQuery *query, + int max_hits) = NULL; +static GSList *(*beagle_hits_subtracted_response_get_uris) (BeagleHitsSubtractedResponse *response) = NULL; + +static struct BeagleDlMapping +{ + const char *fn_name; + gpointer *fn_ptr_ref; +} beagle_dl_mapping[] = +{ +#define MAP(a) { #a, (gpointer *)&a } + MAP (beagle_client_send_request_async), + MAP (beagle_hit_get_uri), + MAP (beagle_hits_added_response_get_hits), + MAP (beagle_query_new), + MAP (beagle_query_add_text), + MAP (beagle_query_part_property_new), + MAP (beagle_query_part_set_logic), + MAP (beagle_query_part_property_set_key), + MAP (beagle_query_part_property_set_value), + MAP (beagle_query_part_property_set_property_type), + MAP (beagle_query_add_part), + MAP (beagle_request_get_type), + MAP (beagle_query_part_get_type), + MAP (beagle_util_daemon_is_running), + MAP (beagle_query_set_max_hits), + MAP (beagle_hits_subtracted_response_get_uris), +#undef MAP + { "beagle_client_new", (gpointer *)&beagle_client_new_real }, +}; + +static void +open_libbeagle (void) +{ + static gboolean done = FALSE; + + if (!done) + { + int i; + GModule *beagle; + + done = TRUE; + + beagle = g_module_open ("libbeagle.so.1", G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + if (!beagle) + return; + + for (i = 0; i < G_N_ELEMENTS (beagle_dl_mapping); i++) + { + if (!g_module_symbol (beagle, beagle_dl_mapping[i].fn_name, + beagle_dl_mapping[i].fn_ptr_ref)) + { + g_warning ("Missing symbol '%s' in libbeagle\n", + beagle_dl_mapping[i].fn_name); + g_module_close (beagle); + + for (i = 0; i < G_N_ELEMENTS (beagle_dl_mapping); i++) + beagle_dl_mapping[i].fn_ptr_ref = NULL; + + return; + } + } + } +} + +static BeagleClient * +beagle_client_new (const char *client_name) +{ + if (beagle_client_new_real) + return beagle_client_new_real (client_name); + + return NULL; +} static void nautilus_search_engine_beagle_class_init (NautilusSearchEngineBeagleClass *class); static void nautilus_search_engine_beagle_init (NautilusSearchEngineBeagle *engine); @@ -276,8 +401,11 @@ nautilus_search_engine_beagle_new (void) { NautilusSearchEngineBeagle *engine; BeagleClient *client; + + open_libbeagle (); - if (!beagle_util_daemon_is_running ()) { + if (beagle_util_daemon_is_running == NULL || + !beagle_util_daemon_is_running ()) { /* check whether daemon is running as beagle_client_new * doesn't fail when a stale socket file exists */ return NULL; diff --git a/libnautilus-private/nautilus-search-engine-tracker.c b/libnautilus-private/nautilus-search-engine-tracker.c index eec8d74..ff1e2d3 100644 --- a/libnautilus-private/nautilus-search-engine-tracker.c +++ b/libnautilus-private/nautilus-search-engine-tracker.c @@ -25,13 +25,103 @@ #include "nautilus-search-engine-tracker.h" #include #include +#include + + +typedef struct _TrackerClient TrackerClient; + +typedef void (*TrackerArrayReply) (char **result, GError *error, gpointer user_data); + +static TrackerClient * (*tracker_connect) (gboolean enable_warnings) = NULL; +static TrackerClient * (*tracker_connect_07) (gboolean enable_warnings, + gint timeout) = NULL; +static void (*tracker_disconnect) (TrackerClient *client) = NULL; +static void (*tracker_cancel_last_call) (TrackerClient *client) = NULL; +static int (*tracker_get_version) (TrackerClient *client, GError **error) = NULL; + + +static void (*tracker_search_metadata_by_text_async) (TrackerClient *client, + const char *query, + TrackerArrayReply callback, + gpointer user_data) = NULL; +static void (*tracker_search_metadata_by_text_and_mime_async) (TrackerClient *client, + const char *query, + const char **mimes, + TrackerArrayReply callback, + gpointer user_data) = NULL; +static void (*tracker_search_metadata_by_text_and_location_async) (TrackerClient *client, + const char *query, + const char *location, + TrackerArrayReply callback, + gpointer user_data) = NULL; +static void (*tracker_search_metadata_by_text_and_mime_and_location_async) (TrackerClient *client, + const char *query, + const char **mimes, + const char *location, + TrackerArrayReply callback, + gpointer user_data) = NULL; + +static struct TrackerDlMapping { + const char *fn_name; + gpointer *fn_ptr_ref; + gboolean mandatory; +} tracker_dl_mapping[] = +{ +#define MAP(a, b) { #a, (gpointer *)&a, b } + MAP (tracker_connect, TRUE), + MAP (tracker_disconnect, TRUE), + MAP (tracker_cancel_last_call, TRUE), + MAP (tracker_search_metadata_by_text_async, TRUE), + MAP (tracker_search_metadata_by_text_and_mime_async, TRUE), + MAP (tracker_search_metadata_by_text_and_location_async, TRUE), + MAP (tracker_search_metadata_by_text_and_mime_and_location_async, TRUE), + MAP (tracker_get_version, FALSE) +#undef MAP +}; + +static gboolean tracker_07; -#ifdef HAVE_TRACKER_0_7 -#include -#else -#include -#endif +static void +open_libtracker (void) +{ + static gboolean done = FALSE; + + if (! done) { + int i; + GModule *tracker; + + done = TRUE; + tracker_07 = TRUE; + tracker_connect_07 = NULL; + + tracker = g_module_open ("libtracker-client-0.7.so.0", G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + if (! tracker) { + tracker = g_module_open ("libtrackerclient.so.0", G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + tracker_07 = FALSE; + } + if (! tracker) + return; + + for (i = 0; i < G_N_ELEMENTS (tracker_dl_mapping); i++) { + if (! g_module_symbol (tracker, tracker_dl_mapping[i].fn_name, + tracker_dl_mapping[i].fn_ptr_ref) && + tracker_dl_mapping[i].mandatory) { + g_warning ("Missing symbol '%s' in libtracker\n", + tracker_dl_mapping[i].fn_name); + g_module_close (tracker); + + for (i = 0; i < G_N_ELEMENTS (tracker_dl_mapping); i++) + tracker_dl_mapping[i].fn_ptr_ref = NULL; + + return; + } + } + if (tracker_07) { + tracker_connect_07 = (gpointer)tracker_connect; + } + } +} struct NautilusSearchEngineTrackerDetails { @@ -96,11 +186,7 @@ search_callback (char **results, GError *error, gpointer user_data) char *uri; -#ifdef HAVE_TRACKER_0_7 - uri = g_strdup ((char *)*results_p); -#else - uri = g_filename_to_uri ((char *)*results_p, NULL, NULL); -#endif + uri = tracker_07 ? g_strdup ((char *)*results_p) : g_filename_to_uri ((char *)*results_p, NULL, NULL); if (uri) { hit_uris = g_list_prepend (hit_uris, (char *)uri); } @@ -139,11 +225,7 @@ nautilus_search_engine_tracker_start (NautilusSearchEngine *engine) location_uri = nautilus_query_get_location (tracker->details->query); if (location_uri) { -#ifdef HAVE_TRACKER_0_7 - location = g_strdup (location_uri); -#else - location = g_filename_from_uri (location_uri, NULL, NULL); -#endif + location = tracker_07 ? g_strdup (location_uri) : g_filename_from_uri (location_uri, NULL, NULL); g_free (location_uri); } else { location = NULL; @@ -271,27 +353,31 @@ nautilus_search_engine_tracker_new (void) NautilusSearchEngineTracker *engine; TrackerClient *tracker_client; -#ifdef HAVE_TRACKER_0_7 - tracker_client = tracker_connect (FALSE, -1); -#else - tracker_client = tracker_connect (FALSE); -#endif + open_libtracker (); + + if (! tracker_connect) + return NULL; + + if (tracker_07) + tracker_client = tracker_connect_07 (FALSE, -1); + else + tracker_client = tracker_connect (FALSE); if (!tracker_client) { return NULL; } -#ifndef HAVE_TRACKER_0_7 - GError *err = NULL; + if (! tracker_07) { + GError *err = NULL; - tracker_get_version (tracker_client, &err); + tracker_get_version (tracker_client, &err); - if (err != NULL) { - g_error_free (err); - tracker_disconnect (tracker_client); - return NULL; + if (err != NULL) { + g_error_free (err); + tracker_disconnect (tracker_client); + return NULL; + } } -#endif engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE_TRACKER, NULL); diff --git a/libnautilus-private/nautilus-search-engine.c b/libnautilus-private/nautilus-search-engine.c index 2030d95..d225237 100644 --- a/libnautilus-private/nautilus-search-engine.c +++ b/libnautilus-private/nautilus-search-engine.c @@ -126,19 +126,15 @@ nautilus_search_engine_new (void) { NautilusSearchEngine *engine; -#ifdef HAVE_BEAGLE engine = nautilus_search_engine_beagle_new (); if (engine) { return engine; } -#endif -#ifdef HAVE_TRACKER engine = nautilus_search_engine_tracker_new (); if (engine) { return engine; } -#endif engine = nautilus_search_engine_simple_new (); return engine; -- 1.6.5.rc2