From: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
To: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCH 3/3 v2] Use libtracker-sparql in PBAP
Date: Wed, 2 Feb 2011 15:15:48 -0300 [thread overview]
Message-ID: <20110202181548.GA13005@piper> (raw)
In-Reply-To: <1296642108-14063-3-git-send-email-ext-jablonski.radoslaw@nokia.com>
Hi Radoslaw,
On 12:21 Wed 02 Feb, Radoslaw Jablonski wrote:
> Now direct tracker connection for transporting retrieved
> parts of data is used, instead of D-Bus. This should result better
> performance for PBAP requests.
> Each part of results is now fetched from tracker asynchronously
> and getting more results can be stopped in any moment -
> GCancellable stored in phonebook_data is used for that purpose.
> If processing of data has finished (or it was cancelled) then cleanup
> of pending_reply is done in last invocation of
> async_query_cursor_next_cb.
> ---
> plugins/phonebook-tracker.c | 271 +++++++++++++++++++++++--------------------
> 1 files changed, 147 insertions(+), 124 deletions(-)
>
> diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
> index 3b61d6b..79bc1c6 100644
> --- a/plugins/phonebook-tracker.c
> +++ b/plugins/phonebook-tracker.c
> @@ -29,6 +29,7 @@
> #include <dbus/dbus.h>
> #include <openobex/obex.h>
> #include <openobex/obex_const.h>
> +#include <libtracker-sparql/tracker-sparql.h>
>
> #include "log.h"
> #include "obex.h"
> @@ -891,7 +892,7 @@
> "} GROUP BY ?call ORDER BY DESC(nmo:receivedDate(?call)) " \
> "LIMIT 40"
>
> -typedef void (*reply_list_foreach_t) (char **reply, int num_fields,
> +typedef void (*reply_list_foreach_t) (const char **reply, int num_fields,
> void *user_data);
>
> typedef void (*add_field_t) (struct phonebook_contact *contact,
> @@ -918,7 +919,7 @@ struct phonebook_data {
> phonebook_cache_ready_cb ready_cb;
> phonebook_entry_cb entry_cb;
> int newmissedcalls;
> - DBusPendingCall *call;
> + GCancellable *query_canc;
> };
>
> struct phonebook_index {
> @@ -926,7 +927,7 @@ struct phonebook_index {
> int index;
> };
>
> -static DBusConnection *connection = NULL;
> +static TrackerSparqlConnection *connection = NULL;
>
> static const char *name2query(const char *name)
> {
> @@ -999,131 +1000,139 @@ static const char *folder2query(const char *folder)
> return NULL;
> }
>
> -static char **string_array_from_iter(DBusMessageIter iter, int array_len)
> +static const char **string_array_from_cursor(TrackerSparqlCursor *cursor,
> + int array_len)
> {
> - DBusMessageIter sub;
> - char **result;
> + const char **result;
> int i;
>
> - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
> - return NULL;
> -
> - result = g_new0(char *, array_len);
> -
> - dbus_message_iter_recurse(&iter, &sub);
> -
> - i = 0;
> - while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
> - char *arg;
> + result = g_new0(const char *, array_len);
>
> - if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
> - g_free(result);
> - return NULL;
> - }
> -
> - dbus_message_iter_get_basic(&sub, &arg);
> + for (i = 0; i < array_len; ++i) {
> + TrackerSparqlValueType type;
>
> - result[i] = arg;
> + type = tracker_sparql_cursor_get_value_type(cursor, i);
>
> - i++;
> - dbus_message_iter_next(&sub);
> + if (type == TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE ||
> + type == TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
> + /* For null/unbound type filling result part with ""*/
> + result[i] = "";
> + else
> + /* Filling with string representation of content*/
> + result[i] = tracker_sparql_cursor_get_string(cursor, i,
> + NULL);
> }
>
> return result;
> }
>
> -static void query_reply(DBusPendingCall *call, void *user_data)
> +
Extra empty line here.
> +static void query_free_data(void *user_data)
> {
> - DBusMessage *reply = dbus_pending_call_steal_reply(call);
> + DBG("");
This statement should go after the declarations.
> struct pending_reply *pending = user_data;
> - DBusMessageIter iter, element;
> - DBusError derr;
> - int err;
> -
> - dbus_error_init(&derr);
> - if (dbus_set_error_from_message(&derr, reply)) {
> - error("Replied with an error: %s, %s", derr.name,
> - derr.message);
> - dbus_error_free(&derr);
> -
> - err = -1;
> - goto done;
> - }
> -
> - dbus_message_iter_init(reply, &iter);
> -
> - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
> - error("SparqlQuery reply is not an array");
>
> - err = -1;
> - goto done;
> - }
> -
> - dbus_message_iter_recurse(&iter, &element);
> -
> - err = 0;
> + if (!pending)
> + return;
g_free() already deals with the case where the pointer is NULL, so I don't see
much point in having this function.
>
> - while (dbus_message_iter_get_arg_type(&element) != DBUS_TYPE_INVALID) {
> - char **node;
> + g_free(pending);
> +}
>
> - if (dbus_message_iter_get_arg_type(&element) !=
> - DBUS_TYPE_ARRAY) {
> - error("element is not an array");
> - goto done;
> - }
> +static void update_cancellable(struct phonebook_data *pdata,
> + GCancellable *canc)
> +{
> + if (pdata->query_canc)
> + g_object_unref(pdata->query_canc);
>
> - node = string_array_from_iter(element, pending->num_fields);
> - pending->callback(node, pending->num_fields,
> - pending->user_data);
> + pdata->query_canc = canc;
> +}
>
> - g_free(node);
> +static void async_query_cursor_next_cb(GObject *source, GAsyncResult *result,
> + gpointer user_data)
> +{
> + struct pending_reply *pending = user_data;
> + TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (source);
Extra space before "(".
> + GCancellable *cancellable;
> + GError *error = NULL;
> + gboolean success;
> + const char **node;
> +
> + success = tracker_sparql_cursor_next_finish(
> + TRACKER_SPARQL_CURSOR (source),
Same here.
> + result,
> + &error);
Perhaps putting these two in the same line?
> +
> + if (!success) {
> + if (error) {
> + DBG("cursor_next error: %s", error->message);
> + g_error_free(error);
> + } else
> + /* When tracker_sparql_cursor_next_finish ends with
> + * failure and no error is set, that means end of
> + * results returned by query */
> + pending->callback(NULL, 0, pending->user_data);
>
> - dbus_message_iter_next(&element);
> + goto failed;
> }
>
> -done:
> - /* This is the last entry */
> - pending->callback(NULL, err, pending->user_data);
> + node = string_array_from_cursor(cursor, pending->num_fields);
> + pending->callback(node, pending->num_fields, pending->user_data);
> + g_free(node);
>
> - dbus_message_unref(reply);
>
> - /* pending data is freed in query_free_data after call is unreffed. */
> -}
> -
> -static void query_free_data(void *user_data)
> -{
> - struct pending_reply *pending = user_data;
> -
> - if (!pending)
> - return;
> + /* getting next row from query results */
> + cancellable = g_cancellable_new();
> + update_cancellable(pending->user_data, cancellable);
> + tracker_sparql_cursor_next_async(cursor, cancellable,
> + async_query_cursor_next_cb,
> + pending);
> + return;
>
> - g_free(pending);
> +failed:
> + g_object_unref(cursor);
> + query_free_data(pending);
> }
>
> -static DBusPendingCall *query_tracker(const char *query, int num_fields,
> - reply_list_foreach_t callback, void *user_data, int *err)
> +static void query_tracker(const char *query, int num_fields,
> + reply_list_foreach_t callback, void *user_data,
> + int *err)
> +
Extra empty line here.
> {
> struct pending_reply *pending;
> - DBusPendingCall *call;
> - DBusMessage *msg;
> + GCancellable *cancellable;
> + TrackerSparqlCursor *cursor;
> + GError *error = NULL;
> +
> + DBG("");
>
> if (connection == NULL)
> - connection = obex_dbus_get_connection();
> + connection = tracker_sparql_connection_get_direct(
> + NULL, &error);
>
> - msg = dbus_message_new_method_call(TRACKER_SERVICE,
> - TRACKER_RESOURCES_PATH, TRACKER_RESOURCES_INTERFACE,
> - "SparqlQuery");
> + if (!connection) {
> + if (error) {
> + DBG("direct-connection error: %s", error->message);
> + g_error_free(error);
> + }
>
> - dbus_message_append_args(msg, DBUS_TYPE_STRING, &query,
> - DBUS_TYPE_INVALID);
> + goto failed;
> + }
>
> - if (dbus_connection_send_with_reply(connection, msg, &call,
> - -1) == FALSE) {
> - error("Could not send dbus message");
> - dbus_message_unref(msg);
> - if (err)
> - *err = -EPERM;
> - return NULL;
> + cancellable = g_cancellable_new();
> + update_cancellable(user_data, cancellable);
> + cursor = tracker_sparql_connection_query(connection, query,
> + cancellable, &error);
> +
> + if (cursor == NULL) {
> + if (error) {
> + DBG("connection_query error: %s", error->message);
> + g_error_free(error);
> + }
> +
> + g_object_unref(cancellable);
> + g_object_unref(cursor);
This looks strange, calling unref on a NULL pointer.
> +
> + goto failed;
> }
>
> pending = g_new0(struct pending_reply, 1);
> @@ -1131,14 +1140,21 @@ static DBusPendingCall *query_tracker(const char *query, int num_fields,
> pending->user_data = user_data;
> pending->num_fields = num_fields;
>
> - dbus_pending_call_set_notify(call, query_reply, pending,
> - query_free_data);
> - dbus_message_unref(msg);
> + /* Now asynchronously going through each row of results - callback
> + * async_query_cursor_next_cb will be called ALWAYS, even if async
> + * request was canceled */
> + tracker_sparql_cursor_next_async(cursor, cancellable,
> + async_query_cursor_next_cb,
> + pending);
>
> if (err)
> *err = 0;
>
> - return call;
> + return;
> +
> +failed:
> + if (err)
> + *err = -EPERM;
> }
>
> static char *iso8601_utc_to_localtime(const char *datetime)
> @@ -1331,7 +1347,8 @@ static GString *gen_vcards(GSList *contacts,
> return vcards;
> }
>
> -static void pull_contacts_size(char **reply, int num_fields, void *user_data)
> +static void pull_contacts_size(const char **reply, int num_fields,
> + void *user_data)
> {
> struct phonebook_data *data = user_data;
>
> @@ -1363,7 +1380,8 @@ static void add_affiliation(char **field, const char *value)
> *field = g_strdup(value);
> }
>
> -static void contact_init(struct phonebook_contact *contact, char **reply)
> +static void contact_init(struct phonebook_contact *contact,
> + const char **reply)
> {
>
> contact->fullname = g_strdup(reply[COL_FULL_NAME]);
> @@ -1395,8 +1413,8 @@ static enum phonebook_number_type get_phone_type(const char *affilation)
> return TEL_TYPE_OTHER;
> }
>
> -static void add_aff_number(struct phonebook_contact *contact, char *pnumber,
> - char *aff_type)
> +static void add_aff_number(struct phonebook_contact *contact,
> + const char *pnumber, const char *aff_type)
> {
> char **num_parts;
> char *type, *number;
> @@ -1433,7 +1451,7 @@ failed:
> }
>
> static void contact_add_numbers(struct phonebook_contact *contact,
> - char **reply)
> + const char **reply)
> {
> char **aff_numbers;
> int i;
> @@ -1459,8 +1477,8 @@ static enum phonebook_field_type get_field_type(const char *affilation)
> return FIELD_TYPE_OTHER;
> }
>
> -static void add_aff_field(struct phonebook_contact *contact, char *aff_email,
> - add_field_t add_field_cb)
> +static void add_aff_field(struct phonebook_contact *contact,
> + const char *aff_email, add_field_t add_field_cb)
> {
> char **email_parts;
> char *type, *email;
> @@ -1490,7 +1508,7 @@ failed:
> }
>
> static void contact_add_emails(struct phonebook_contact *contact,
> - char **reply)
> + const char **reply)
> {
> char **aff_emails;
> int i;
> @@ -1506,7 +1524,7 @@ static void contact_add_emails(struct phonebook_contact *contact,
> }
>
> static void contact_add_addresses(struct phonebook_contact *contact,
> - char **reply)
> + const char **reply)
> {
> char **aff_addr;
> int i;
> @@ -1522,7 +1540,8 @@ static void contact_add_addresses(struct phonebook_contact *contact,
> g_strfreev(aff_addr);
> }
>
> -static void contact_add_urls(struct phonebook_contact *contact, char **reply)
> +static void contact_add_urls(struct phonebook_contact *contact,
> + const char **reply)
> {
> char **aff_url;
> int i;
> @@ -1538,7 +1557,7 @@ static void contact_add_urls(struct phonebook_contact *contact, char **reply)
> }
>
> static void contact_add_organization(struct phonebook_contact *contact,
> - char **reply)
> + const char **reply)
> {
> /* Adding fields connected by nco:hasAffiliation - they may be in
> * separate replies */
> @@ -1548,7 +1567,7 @@ static void contact_add_organization(struct phonebook_contact *contact,
> add_affiliation(&contact->role, reply[COL_ORG_ROLE]);
> }
>
> -static void pull_contacts(char **reply, int num_fields, void *user_data)
> +static void pull_contacts(const char **reply, int num_fields, void *user_data)
> {
> struct phonebook_data *data = user_data;
> const struct apparam_field *params = data->params;
> @@ -1649,7 +1668,7 @@ fail:
> */
> }
>
> -static void add_to_cache(char **reply, int num_fields, void *user_data)
> +static void add_to_cache(const char **reply, int num_fields, void *user_data)
> {
> struct phonebook_data *data = user_data;
> char *formatted;
> @@ -1699,6 +1718,9 @@ done:
>
> int phonebook_init(void)
> {
> + g_thread_init(NULL);
> + g_type_init();
> +
> return 0;
> }
>
> @@ -1792,12 +1814,13 @@ void phonebook_req_finalize(void *request)
> if (!data)
> return;
>
> - if (!dbus_pending_call_get_completed(data->call))
> - dbus_pending_call_cancel(data->call);
> -
> - dbus_pending_call_unref(data->call);
> + /* canceling asynchronous operation on tracker if any is active */
> + if (data->query_canc) {
> + g_cancellable_cancel(data->query_canc);
> + g_object_unref(data->query_canc);
> + }
>
> - /* freeing list of contacts used for generating vcards */
> + /* freeing contacts */
> for (l = data->contacts; l; l = l->next) {
> struct contact_data *c_data = l->data;
>
> @@ -1828,7 +1851,8 @@ static void gstring_free_helper(gpointer data, gpointer user_data)
> g_string_free(data, TRUE);
> }
>
> -static void pull_newmissedcalls(char **reply, int num_fields, void *user_data)
> +static void pull_newmissedcalls(const char **reply, int num_fields,
> + void *user_data)
> {
> struct phonebook_data *data = user_data;
> reply_list_foreach_t pull_cb;
> @@ -1870,8 +1894,7 @@ done:
> pull_cb = pull_contacts;
> }
>
> - dbus_pending_call_unref(data->call);
> - data->call = query_tracker(query, col_amount, pull_cb, data, &err);
> + query_tracker(query, col_amount, pull_cb, data, &err);
> if (err < 0)
> data->cb(NULL, 0, err, 0, data->user_data);
> }
> @@ -1910,7 +1933,7 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
> data->params = params;
> data->user_data = user_data;
> data->cb = cb;
> - data->call = query_tracker(query, col_amount, pull_cb, data, err);
> + query_tracker(query, col_amount, pull_cb, data, err);
>
> return data;
> }
> @@ -1938,8 +1961,8 @@ void *phonebook_get_entry(const char *folder, const char *id,
> query = g_strdup_printf(CONTACTS_OTHER_QUERY_FROM_URI,
> id, id, id);
>
> - data->call = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts,
> - data, err);
> + query_tracker(query, PULL_QUERY_COL_AMOUNT,
> + pull_contacts, data, err);
>
> g_free(query);
>
> @@ -1965,7 +1988,7 @@ void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
> data->entry_cb = entry_cb;
> data->ready_cb = ready_cb;
> data->user_data = user_data;
> - data->call = query_tracker(query, 7, add_to_cache, data, err);
> + query_tracker(query, 7, add_to_cache, data, err);
>
> return data;
> }
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Cheers,
--
Vinicius
prev parent reply other threads:[~2011-02-02 18:15 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-02 10:21 [PATCH 1/3 v2] Add libtracker-sparql to obexd dependencies Radoslaw Jablonski
2011-02-02 10:21 ` [PATCH 2/3 v2] Move freeing contacts data to phonebook_req_finalize Radoslaw Jablonski
2011-02-02 10:21 ` [PATCH 3/3 v2] Use libtracker-sparql in PBAP Radoslaw Jablonski
2011-02-02 18:15 ` Vinicius Costa Gomes [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110202181548.GA13005@piper \
--to=vinicius.gomes@openbossa.org \
--cc=ext-jablonski.radoslaw@nokia.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox