Commit 193cd7bd authored by Martyn James Russell's avatar Martyn James Russell

Added command line switches to faciliate the _get() and _get_multiple()

	* src/tracker-utils/tracker-info.c: Added command line switches to
	faciliate the _get() and _get_multiple() APIs for Metadata. Now we
	can request multiple specific metadata types for multiple files
	using tracker-info.

	* data/dbus/tracker-metadata.xml:
	* src/libtracker/tracker.[ch]: 
	* src/trackerd/tracker-metadata.[ch]: Added
	tracker_metadata_get_multiple() so we can get multiple metadata
	types for multiple files. This is quite a bit faster than
	requesting multiple metadata types for one file at a time. Fixes
	NB#108543.

svn path=/trunk/; revision=3160
parent ee5e3e54
2009-04-01 Martyn Russell <martyn@imendio.com>
* src/tracker-utils/tracker-info.c: Added command line switches to
faciliate the _get() and _get_multiple() APIs for Metadata. Now we
can request multiple specific metadata types for multiple files
using tracker-info.
* data/dbus/tracker-metadata.xml:
* src/libtracker/tracker.[ch]:
* src/trackerd/tracker-metadata.[ch]: Added
tracker_metadata_get_multiple() so we can get multiple metadata
types for multiple files. This is quite a bit faster than
requesting multiple metadata types for one file at a time. Fixes
NB#108543.
2009-04-01 Carlos Garnacho <carlos@imendio.com> 2009-04-01 Carlos Garnacho <carlos@imendio.com>
* src/tracker-indexer/tracker-indexer.c (mount_pre_unmount_cb): Check * src/tracker-indexer/tracker-indexer.c (mount_pre_unmount_cb): Check
......
...@@ -24,6 +24,17 @@ ...@@ -24,6 +24,17 @@
<arg type="aas" name="metadata" direction="out" /> <arg type="aas" name="metadata" direction="out" />
</method> </method>
<!-- Retrieves an array of metadata values for the specified array
of metadata keys for services and id pair.
-->
<method name="GetMultiple">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg type="s" name="service_type" direction="in" />
<arg type="as" name="uris" direction="in" />
<arg type="as" name="keys" direction="in" />
<arg type="aas" name="metadata" direction="out" />
</method>
<!-- Sets specified metadata keys to the specified metadata values <!-- Sets specified metadata keys to the specified metadata values
for a service and id pair. for a service and id pair.
--> -->
......
...@@ -441,6 +441,19 @@ tracker_metadata_get (TrackerClient *client, ServiceType service, const char *id ...@@ -441,6 +441,19 @@ tracker_metadata_get (TrackerClient *client, ServiceType service, const char *id
return array; return array;
} }
GPtrArray *
tracker_metadata_get_multiple (TrackerClient *client, ServiceType service, const char **ids, const char **keys, GError **error)
{
GPtrArray *array = NULL;
const char *service_str = tracker_service_types[service];
if (!org_freedesktop_Tracker_Metadata_get_multiple (client->proxy_metadata, service_str, ids, keys, &array, error)) {
return NULL;
}
return array;
}
GPtrArray * GPtrArray *
tracker_metadata_get_all (TrackerClient *client, ServiceType service, const gchar *uri, GError **error) tracker_metadata_get_all (TrackerClient *client, ServiceType service, const gchar *uri, GError **error)
{ {
...@@ -1096,6 +1109,23 @@ tracker_metadata_get_async (TrackerClient *client, ServiceType service, const ch ...@@ -1096,6 +1109,23 @@ tracker_metadata_get_async (TrackerClient *client, ServiceType service, const ch
} }
void
tracker_metadata_get_multiple_async (TrackerClient *client, ServiceType service, const char **ids, const char **keys, TrackerGPtrArrayReply callback, gpointer user_data)
{
GPtrArrayCallBackStruct *callback_struct;
const char *service_str;
callback_struct = g_new (GPtrArrayCallBackStruct, 1);
callback_struct->callback = callback;
callback_struct->data = user_data;
service_str = tracker_service_types[service];
client->last_pending_call = org_freedesktop_Tracker_Metadata_get_multiple_async (client->proxy_metadata, service_str, ids, keys, tracker_GPtrArray_reply, callback_struct);
}
void void
tracker_metadata_set_async (TrackerClient *client, ServiceType service, const char *id, const char **keys, char **values, TrackerVoidReply callback, gpointer user_data) tracker_metadata_set_async (TrackerClient *client, ServiceType service, const char *id, const char **keys, char **values, TrackerVoidReply callback, gpointer user_data)
{ {
......
...@@ -119,6 +119,7 @@ void tracker_shutdown (TrackerClient *client, gboolean reindex, GError **err ...@@ -119,6 +119,7 @@ void tracker_shutdown (TrackerClient *client, gboolean reindex, GError **err
void tracker_prompt_index_signals (TrackerClient *client, GError **error); void tracker_prompt_index_signals (TrackerClient *client, GError **error);
char ** tracker_metadata_get (TrackerClient *client, ServiceType service, const char *id, const char **keys, GError **error); char ** tracker_metadata_get (TrackerClient *client, ServiceType service, const char *id, const char **keys, GError **error);
GPtrArray * tracker_metadata_get_multiple (TrackerClient *client, ServiceType service, const char **ids, const char **keys, GError **error);
GPtrArray * tracker_metadata_get_all (TrackerClient *client, ServiceType service, const gchar *uri, GError **error); GPtrArray * tracker_metadata_get_all (TrackerClient *client, ServiceType service, const gchar *uri, GError **error);
void tracker_metadata_set (TrackerClient *client, ServiceType service, const char *id, const char **keys, char **values, GError **error); void tracker_metadata_set (TrackerClient *client, ServiceType service, const char *id, const char **keys, char **values, GError **error);
void tracker_metadata_register_type (TrackerClient *client, const char *name, MetadataTypes type, GError **error); void tracker_metadata_register_type (TrackerClient *client, const char *name, MetadataTypes type, GError **error);
...@@ -185,6 +186,7 @@ void tracker_shutdown_async (TrackerClient *client, gboolean reindex, Track ...@@ -185,6 +186,7 @@ void tracker_shutdown_async (TrackerClient *client, gboolean reindex, Track
void tracker_prompt_index_signals_async (TrackerClient *client, TrackerVoidReply callback, gpointer user_data); void tracker_prompt_index_signals_async (TrackerClient *client, TrackerVoidReply callback, gpointer user_data);
void tracker_metadata_get_async (TrackerClient *client, ServiceType service, const char *id, const char **keys, TrackerArrayReply callback, gpointer user_data); void tracker_metadata_get_async (TrackerClient *client, ServiceType service, const char *id, const char **keys, TrackerArrayReply callback, gpointer user_data);
void tracker_metadata_get_multiple_async (TrackerClient *client, ServiceType service, const char **ids, const char **keys, TrackerGPtrArrayReply callback, gpointer user_data);
void tracker_metadata_set_async (TrackerClient *client, ServiceType service, const char *id, const char **keys, char **values, TrackerVoidReply callback, gpointer user_data); void tracker_metadata_set_async (TrackerClient *client, ServiceType service, const char *id, const char **keys, char **values, TrackerVoidReply callback, gpointer user_data);
void tracker_metadata_register_type_async (TrackerClient *client, const char *name, MetadataTypes type, TrackerVoidReply callback, gpointer user_data); void tracker_metadata_register_type_async (TrackerClient *client, const char *name, MetadataTypes type, TrackerVoidReply callback, gpointer user_data);
void tracker_metadata_get_registered_types_async (TrackerClient *client, const char *classname, TrackerArrayReply callback, gpointer user_data); void tracker_metadata_get_registered_types_async (TrackerClient *client, const char *classname, TrackerArrayReply callback, gpointer user_data);
......
...@@ -34,28 +34,55 @@ ...@@ -34,28 +34,55 @@
#include <libtracker-common/tracker-common.h> #include <libtracker-common/tracker-common.h>
static gchar *service; static gchar *service;
static gchar **uri = NULL; static gchar **metadata;
static gchar **uris;
static GOptionEntry entries[] = { static GOptionEntry entries[] = {
{ "service", 's', 0, G_OPTION_ARG_STRING, &service, { "service", 's', 0, G_OPTION_ARG_STRING, &service,
N_("Service type of the file"), N_("Service type of the file"),
NULL N_("Files")
}, },
{ G_OPTION_REMAINING, 0, { "metadata", 'm', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING_ARRAY, &metadata,
G_OPTION_FLAG_FILENAME, G_OPTION_ARG_STRING_ARRAY, &uri, N_("Metadata to request (optional, multiple calls allowed)"),
N_("File:Size")
},
{ G_OPTION_REMAINING, 0, G_OPTION_FLAG_FILENAME, G_OPTION_ARG_FILENAME_ARRAY, &uris,
N_("FILE..."), N_("FILE..."),
N_("FILE")}, N_("FILE")
},
{ NULL } { NULL }
}; };
static void static void
print_property_value (gpointer value) print_property_value (gpointer data,
gpointer user_data)
{ {
gchar **pair; GStrv results;
GStrv uris_used;
results = data;
uris_used = user_data;
if (uris_used) {
static gint uri_id = 0;
GStrv p;
gint i;
pair = value; g_print ("%s\n", uris_used[uri_id]);
if (!results) {
g_print (" %s\n", _("No metadata available"));
return;
}
g_print (" '%s' = '%s'\n", pair[0], pair[1]); for (p = results, i = 0; *p; p++, i++) {
g_print (" '%s' = '%s'\n", metadata[i], *p);
}
uri_id++;
} else {
g_print (" '%s' = '%s'\n", results[0], results[1]);
}
} }
int int
...@@ -64,10 +91,13 @@ main (int argc, char **argv) ...@@ -64,10 +91,13 @@ main (int argc, char **argv)
TrackerClient *client; TrackerClient *client;
ServiceType type; ServiceType type;
GFile *file; GFile *file;
gchar *abs_path; gchar *summary;
gchar *path;
GOptionContext *context; GOptionContext *context;
GError *error = NULL; GError *error = NULL;
GPtrArray *results; guint count;
gint i;
gint exit_result = EXIT_SUCCESS;
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
...@@ -81,14 +111,34 @@ main (int argc, char **argv) ...@@ -81,14 +111,34 @@ main (int argc, char **argv)
/* Translators: this message will appear after the usage string */ /* Translators: this message will appear after the usage string */
/* and before the list of options. */ /* and before the list of options. */
summary = g_strconcat (_("For a list of services and metadata that "
"can be used here, see tracker-services."),
NULL);
g_option_context_set_summary (context, summary);
g_option_context_add_main_entries (context, entries, NULL); g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL); g_option_context_parse (context, &argc, &argv, NULL);
g_free (summary);
if (!uris) {
gchar *help;
g_printerr (_("URI missing"));
g_printerr ("\n\n");
help = g_option_context_get_help (context, TRUE, NULL);
g_option_context_free (context);
g_printerr ("%s", help);
g_free (help);
return EXIT_FAILURE;
}
if (!uri) { if (!metadata && g_strv_length (uris) > 1) {
gchar *help; gchar *help;
g_printerr ("%s\n\n", g_printerr (_("Requesting ALL information about multiple files is not supported"));
_("Uri missing")); g_printerr ("\n\n");
help = g_option_context_get_help (context, TRUE, NULL); help = g_option_context_get_help (context, TRUE, NULL);
g_option_context_free (context); g_option_context_free (context);
...@@ -103,67 +153,154 @@ main (int argc, char **argv) ...@@ -103,67 +153,154 @@ main (int argc, char **argv)
client = tracker_connect (FALSE); client = tracker_connect (FALSE);
if (!client) { if (!client) {
g_printerr ("%s\n", g_printerr (_("Could not establish a DBus connection to Tracker"));
_("Could not establish a DBus connection to Tracker")); g_printerr ("\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!service) { if (!service) {
g_print ("%s\n", g_print (_("Defaulting to 'files' service"));
_("Defaulting to 'files' service")); g_print ("\n");
type = SERVICE_FILES; type = SERVICE_FILES;
} else { } else {
type = tracker_service_name_to_type (service); type = tracker_service_name_to_type (service);
if (type == SERVICE_OTHER_FILES && g_ascii_strcasecmp (service, "Other")) { if (type == SERVICE_OTHER_FILES && g_ascii_strcasecmp (service, "Other")) {
g_printerr ("%s\n", g_printerr (_("Service type not recognized, using 'Other' ..."));
_("Service type not recognized, using 'Other' ...")); g_printerr ("\n");
} }
} }
file = g_file_new_for_commandline_arg (uri[0]); count = g_strv_length (uris);
abs_path = g_file_get_path (file);
results = tracker_metadata_get_all (client, if (count > 1 && metadata != NULL) {
type, gchar **strv;
abs_path, GPtrArray *results;
&error);
g_free (abs_path); strv = g_new (gchar*, count + 1);
g_object_unref (file);
/* Convert all files to real paths */
if (error) { for (i = 0; i < count; i++) {
g_printerr ("%s, %s\n", file = g_file_new_for_commandline_arg (uris[i]);
_("Unable to retrieve data for uri"), path = g_file_get_path (file);
error->message); g_object_unref (file);
g_error_free (error); strv[i] = path;
tracker_disconnect (client); }
strv[i] = NULL;
return EXIT_FAILURE; results = tracker_metadata_get_multiple (client,
} type,
(const gchar **) strv,
(const gchar **) metadata,
&error);
if (!results) { if (error) {
g_print ("%s\n", g_printerr (_("Unable to retrieve data for %d uris"),
_("No metadata available for that uri")); count);
} else { g_printerr (", %s\n",
gint length; error->message);
g_error_free (error);
exit_result = EXIT_FAILURE;
} else if (!results) {
g_print (_("No metadata available for all %d uris"),
count);
g_print ("\n");
} else {
g_print (_("Results:"));
g_print ("\n");
g_ptr_array_foreach (results, print_property_value, strv);
g_ptr_array_foreach (results, (GFunc) g_strfreev, NULL);
g_ptr_array_free (results, TRUE);
}
length = results->len; g_strfreev (strv);
} else {
GPtrArray *results;
g_print (tracker_dngettext (NULL, file = g_file_new_for_commandline_arg (uris[0]);
_("Result: %d"), path = g_file_get_path (file);
_("Results: %d"),
length),
length);
g_print ("\n");
g_ptr_array_foreach (results, (GFunc) print_property_value, NULL); if (G_LIKELY (!metadata)) {
g_ptr_array_foreach (results, (GFunc) g_strfreev, NULL); results = tracker_metadata_get_all (client,
g_ptr_array_free (results, TRUE); type,
path,
&error);
if (error) {
g_printerr ("%s, %s\n",
_("Unable to retrieve data for uri"),
error->message);
g_error_free (error);
exit_result = EXIT_FAILURE;
} else if (!results) {
g_print (_("No metadata available for that uri"));
g_print ("\n");
} else {
gint length;
length = results->len;
g_print (tracker_dngettext (NULL,
_("Result: %d for '%s'"),
_("Results: %d for '%s'"),
length),
length,
path);
g_print ("\n");
g_ptr_array_foreach (results, print_property_value, NULL);
g_ptr_array_foreach (results, (GFunc) g_strfreev, NULL);
g_ptr_array_free (results, TRUE);
}
} else {
GStrv results;
results = tracker_metadata_get (client,
type,
path,
(const gchar **) metadata,
&error);
if (error) {
g_printerr ("%s, %s\n",
_("Unable to retrieve data for uri"),
error->message);
g_error_free (error);
exit_result = EXIT_FAILURE;
} else if (!results) {
g_print (_("No metadata available for that uri"));
g_print ("\n");
} else {
gint length;
gint i;
length = g_strv_length (results);
g_print (_("Results:"));
g_print ("\n");
for (i = 0; i < length; i++) {
g_print (" '%s' = '%s'\n",
metadata[i], results[i]);
}
g_strfreev (results);
}
}
g_object_unref (file);
g_free (path);
} }
tracker_disconnect (client); tracker_disconnect (client);
return EXIT_SUCCESS; return exit_result;
} }
...@@ -65,88 +65,62 @@ tracker_metadata_new (void) ...@@ -65,88 +65,62 @@ tracker_metadata_new (void)
* Functions * Functions
*/ */
void static gchar **
tracker_metadata_get (TrackerMetadata *object, tracker_metadata_get_internal (TrackerMetadata *object,
const gchar *service_type, guint request_id,
const gchar *uri, const gchar *service_type,
gchar **keys, const gchar *uri,
DBusGMethodInvocation *context, gchar **keys,
GError **error) GError **error)
{ {
TrackerDBInterface *iface; TrackerDBInterface *iface;
TrackerDBResultSet *result_set; TrackerDBResultSet *result_set;
guint request_id;
const gchar *service_result; const gchar *service_result;
guint32 service_id; guint32 service_id;
gchar *service_id_str; gchar *service_id_str;
guint i; guint i;
gchar **values; gchar **values;
GError *actual_error = NULL;
request_id = tracker_dbus_get_next_request_id ();
tracker_dbus_async_return_if_fail (service_type != NULL, context);
tracker_dbus_async_return_if_fail (uri != NULL, context);
tracker_dbus_async_return_if_fail (keys != NULL, context);
tracker_dbus_async_return_if_fail (g_strv_length (keys) > 0, context);
tracker_dbus_request_new (request_id,
"DBus request to get metadata values, "
"service type:'%s'",
service_type);
if (!tracker_ontology_service_is_valid (service_type)) { if (!tracker_ontology_service_is_valid (service_type)) {
tracker_dbus_request_failed (request_id, tracker_dbus_request_failed (request_id,
&actual_error, error,
"Service '%s' is invalid or has not been implemented yet", "Service '%s' is invalid or has not been implemented yet",
service_type); service_type);
dbus_g_method_return_error (context, actual_error); return NULL;
g_error_free (actual_error);
return;
} }
service_id = tracker_data_query_file_id (service_type, uri); service_id = tracker_data_query_file_id (service_type, uri);
if (service_id <= 0) { if (service_id <= 0) {
tracker_dbus_request_failed (request_id, tracker_dbus_request_failed (request_id,
&actual_error, error,
"Service URI '%s' not found", "Service URI '%s' not found",
uri); uri);
dbus_g_method_return_error (context, actual_error); return NULL;
g_error_free (actual_error);
return;
} }
/* Checking keys */ /* Checking keys */
for (i = 0; i < g_strv_length (keys); i++) { for (i = 0; i < g_strv_length (keys); i++) {
if (tracker_ontology_get_field_by_name (keys[i]) == NULL) { if (tracker_ontology_get_field_by_name (keys[i]) == NULL) {
tracker_dbus_request_failed (request_id, tracker_dbus_request_failed (request_id,
&actual_error, error,
"Metadata field '%s' not registered in the system", "Metadata field '%s' not registered in the system",
keys[i]); keys[i]);
dbus_g_method_return_error (context, actual_error); return NULL;
g_error_free (actual_error);
return;
} }
} }
/* The parameter service_type can be "Files" /* Get database interface */
* and the actual service type of the uri "Video"
*
* Note: Does this matter?
*/
iface = tracker_db_manager_get_db_interface_by_service (service_type); iface = tracker_db_manager_get_db_interface_by_service (service_type);
/* Check we have a file in the database before looking up the metadata. */
service_result = tracker_data_query_service_type_by_id (iface, service_id); service_result = tracker_data_query_service_type_by_id (iface, service_id);
if (!service_result) { if (!service_result) {
tracker_dbus_request_failed (request_id, tracker_dbus_request_failed (request_id,
&actual_error, error,
"Service type can not be found for entity '%s'", "Service type can not be found for entity '%s'",
uri); uri);
dbus_g_method_return_error (context, actual_error); return NULL;
g_error_free (actual_error);
return;
} }
service_id_str = tracker_guint_to_string (service_id); service_id_str = tracker_guint_to_string (service_id);
...@@ -162,10 +136,49 @@ tracker_metadata_get (TrackerMetadata *object, ...@@ -162,10 +136,49 @@ tracker_metadata_get (TrackerMetadata *object,
if (!values) { if (!values) {
tracker_dbus_request_failed (request_id, tracker_dbus_request_failed (request_id,
&actual_error, error,
"No metadata information was available"); "No metadata information was available");
return NULL;
}
return values;
}
void
tracker_metadata_get (TrackerMetadata *object,
const gchar *service_type,
const gchar *uri,
gchar **keys,
DBusGMethodInvocation *context,
GError **error)
{
guint request_id;
gchar **values;
GError *actual_error = NULL;
request_id = tracker_dbus_get_next_request_id ();
tracker_dbus_async_return_if_fail (service_type != NULL, context);
tracker_dbus_async_return_if_fail (uri != NULL, context);
tracker_dbus_async_return_if_fail (keys != NULL, context);
tracker_dbus_async_return_if_fail (g_strv_length (keys) > 0, context);
tracker_dbus_request_new (request_id,
"DBus request to get metadata values, "
"service type:'%s'",
service_type);
values = tracker_metadata_get_internal (object,
request_id,
service_type,
uri,
keys,
&actual_error);
if (!values) {
dbus_g_method_return_error (context, actual_error); dbus_g_method_return_error (context, actual_error);
g_error_free (actual_error); g_error_free (actual_error);
return;
} }
dbus_g_method_return (context, values); dbus_g_method_return (context, values);
...@@ -175,11 +188,66 @@ tracker_metadata_get (TrackerMetadata *object, ...@@ -175,11 +188,66 @@ tracker_metadata_get (TrackerMetadata *object,
} }
void void
tracker_metadata_get_all (TrackerMetadata *object, tracker_metadata_get_multiple (TrackerMetadata *object,
const gchar *service_type, const gchar *service_type,
const gchar *uri, const gchar **uris,
DBusGMethodInvocation *context, gchar **keys,
GError **error) DBusGMethodInvocation *context,
GError **error)
{
guint request_id;
guint count;
gint i;
GPtrArray *values;
GError *actual_error = NULL;
request_id = tracker_dbus_get_next_request_id ();
tracker_dbus_async_return_if_fail (service_type != NULL, context);
tracker_dbus_async_return_if_fail (uris != NULL, context);
tracker_dbus_async_return_if_fail (keys != NULL, context);
tracker_dbus_async_return_if_fail (g_strv_length (keys) > 0, context);
tracker_dbus_request_new (request_id,
"DBus request to get multiple metadata values, "
"service type:'%s'",
service_type);
count = g_strv_length ((GStrv) uris);
values = g_ptr_array_sized_new (count);
for (i = 0; i < count && !actual_error; i++) {
GStrv strv;
strv = tracker_metadata_get_internal (object,
request_id,
service_type,
uris[i],
keys,
&actual_error);
/* Don't allow errors, but allow NULLs */
g_ptr_array_add (values, strv);
}
if (G_UNLIKELY (actual_error)) {
dbus_g_method_return_error (context, actual_error);
g_error_free (actual_error);
} else {