summaryrefslogtreecommitdiffstats
path: root/source3/utils/async-tracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils/async-tracker.c')
-rw-r--r--source3/utils/async-tracker.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/source3/utils/async-tracker.c b/source3/utils/async-tracker.c
new file mode 100644
index 0000000..7b6c2c0
--- /dev/null
+++ b/source3/utils/async-tracker.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2011, Nokia <ivan.frade@nokia.com>
+ * Copyright (C) 2015, Noel Power <nopower@suse.com>
+ * Copyright (C) 2016, Ralph Boehme <slow@samba.org.>
+ *
+ * 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.
+ */
+
+#include "includes.h"
+#include "lib/util/debug.h"
+#include "lib/cmdline/cmdline.h"
+#include "param.h"
+/*
+ * glib uses TRUE and FALSE which was redefined by "includes.h" to be
+ * unusable, undefine so glib can establish its own working
+ * replacement.
+ */
+#undef TRUE
+#undef FALSE
+#include <glib.h>
+#include <libtracker-sparql/tracker-sparql.h>
+#include "lib/tevent_glib_glue.h"
+
+enum loop_type {TEVENT_LOOP, GLIB_LOOP};
+
+struct test_state {
+ enum loop_type loop_type;
+ TrackerSparqlConnection *connection;
+ GCancellable *cancellable;
+ GTimer *timer;
+ GMainLoop *loop;
+ struct tevent_context *ev;
+ struct tevent_glib_glue *glue;
+};
+
+static void cleanup(struct test_state *state)
+{
+ g_cancellable_cancel(state->cancellable);
+ g_object_unref(state->cancellable);
+ g_timer_destroy(state->timer);
+ if (state->connection != NULL) {
+ g_object_unref(state->connection);
+ state->connection = NULL;
+ }
+ if (state->loop_type == GLIB_LOOP) {
+ g_main_loop_quit(state->loop);
+ } else {
+ samba_tevent_glib_glue_quit(state->glue);
+ }
+}
+
+static void cursor_cb(GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ struct test_state *state = talloc_get_type_abort(
+ user_data, struct test_state);
+ TrackerSparqlCursor *cursor = NULL;
+ GError *error = NULL;
+ gboolean more_results;
+ static gint i = 0;
+
+ cursor = TRACKER_SPARQL_CURSOR(object);
+ more_results = tracker_sparql_cursor_next_finish(cursor,
+ res,
+ &error);
+ if (error) {
+ g_critical("Could not run cursor next: %s", error->message);
+
+ if (cursor != NULL) {
+ g_object_unref(cursor);
+ }
+
+ g_error_free(error);
+ cleanup(state);
+ return;
+ }
+
+ if (!more_results) {
+ g_print("\n");
+ g_print("\nAsync cursor next took: %.6f (for all %d results)\n",
+ g_timer_elapsed (state->timer, NULL), i);
+
+ g_object_unref(cursor);
+ cleanup(state);
+ return;
+ }
+
+ if (i++ < 5) {
+ int num_cols = tracker_sparql_cursor_get_n_columns(cursor);
+ int col;
+
+ if (i == 1) {
+ g_print("Printing first 5 results:\n");
+ }
+ for (col = 0; col < num_cols; col++) {
+ g_print(" %s ", tracker_sparql_cursor_get_string(
+ cursor, col, NULL));
+ if (col == num_cols -1 ) {
+ g_print("\n");
+ }
+ }
+
+ if (i == 5) {
+ g_print(" ...\n");
+ g_print(" Printing nothing for remaining results\n");
+ }
+ }
+
+ tracker_sparql_cursor_next_async(cursor,
+ state->cancellable,
+ cursor_cb,
+ state);
+}
+
+static void query_cb(GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ struct test_state *state = talloc_get_type_abort(
+ user_data, struct test_state);
+ TrackerSparqlCursor *cursor = NULL;
+ GError *error = NULL;
+
+ g_print("Async query took: %.6f\n", g_timer_elapsed(state->timer, NULL));
+
+ cursor = tracker_sparql_connection_query_finish(
+ TRACKER_SPARQL_CONNECTION(object),
+ res,
+ &error);
+ if (error) {
+ g_critical("Could not run query: %s", error->message);
+
+ if (cursor) {
+ g_object_unref(cursor);
+ }
+
+ g_error_free(error);
+ cleanup(state);
+ return;
+ }
+
+ g_timer_start(state->timer);
+
+ tracker_sparql_cursor_next_async(cursor,
+ state->cancellable,
+ cursor_cb,
+ state);
+}
+
+static void connection_cb(GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ struct test_state *state = talloc_get_type_abort(
+ user_data, struct test_state);
+ GError *error = NULL;
+
+ g_print("Async connection took: %.6f\n",
+ g_timer_elapsed(state->timer, NULL));
+
+ state->connection = tracker_sparql_connection_get_finish(res, &error);
+ if (error) {
+ g_critical("Could not connect: %s", error->message);
+ g_error_free(error);
+ cleanup(state);
+ return;
+ }
+
+ g_timer_start(state->timer);
+
+ tracker_sparql_connection_query_async(
+ state->connection,
+ "SELECT ?name nie:mimeType(?s) nfo:fileName(?s) "
+ "WHERE { {?s nie:url ?name}}",
+ state->cancellable,
+ query_cb,
+ state);
+}
+
+static void debug_fn(void *private_data,
+ enum tevent_debug_level level,
+ const char *fmt,
+ va_list ap)
+{
+ dbgtext_va(fmt, ap);
+}
+
+int main(int argc, const char **argv)
+{
+ TALLOC_CTX *mem_ctx = NULL;
+ struct test_state *state = NULL;
+ int c;
+ poptContext pc;
+ bool ok;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {
+ .longName = "tevent",
+ .shortName = 't',
+ .argInfo = POPT_ARG_NONE,
+ .val = 'v',
+ .descrip = "Use tevent loop",
+ },
+ {
+ .longName = "glib",
+ .shortName = 'g',
+ .argInfo = POPT_ARG_NONE,
+ .val = 'g',
+ .descrip = "Use glib loop",
+ },
+ POPT_COMMON_SAMBA
+ POPT_COMMON_VERSION
+ POPT_TABLEEND
+ };
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ exit(1);
+ }
+
+ state = talloc_zero(mem_ctx, struct test_state);
+ if (state == NULL) {
+ exit(1);
+ }
+
+ state->loop_type = TEVENT_LOOP;
+
+ smb_init_locale();
+
+ ok = samba_cmdline_init(mem_ctx,
+ SAMBA_CMDLINE_CONFIG_CLIENT,
+ true /* require_smbconf */);
+ if (!ok) {
+ TALLOC_FREE(mem_ctx);
+ exit(1);
+ }
+
+ pc = samba_popt_get_context(getprogname(),
+ argc,
+ argv,
+ long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+ if (pc == NULL) {
+ TALLOC_FREE(mem_ctx);
+ exit(1);
+ }
+
+ while ((c = poptGetNextOpt(pc)) != -1) {
+ switch (c) {
+ case 'g':
+ state->loop_type = GLIB_LOOP;
+ break;
+ case 't':
+ state->loop_type = TEVENT_LOOP;
+ break;
+ case POPT_ERROR_BADOPT:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(c));
+ poptPrintUsage(pc, stderr, 0);
+ exit(1);
+ }
+ }
+
+ if (state->loop_type == GLIB_LOOP) {
+ state->loop = g_main_loop_new(NULL, false);
+ } else {
+ state->ev = tevent_context_init(mem_ctx);
+ if (CHECK_DEBUGLVL(10)) {
+ tevent_set_debug(state->ev, debug_fn, NULL);
+ }
+ state->glue = samba_tevent_glib_glue_create(
+ mem_ctx, state->ev, g_main_context_default());
+ if (state->glue == NULL) {
+ printf("tevent_glib_glue_create failed\n");
+ exit(1);
+ }
+ }
+
+ state->timer = g_timer_new();
+ state->cancellable = g_cancellable_new();
+
+ tracker_sparql_connection_get_async(state->cancellable,
+ connection_cb,
+ state);
+
+ if (state->loop_type == GLIB_LOOP) {
+ printf("entering g_main_loop_run\n");
+ g_main_loop_run(state->loop);
+ } else {
+ printf("entering tevent_loop_wait\n");
+ tevent_loop_wait(state->ev);
+
+ TALLOC_FREE(state->glue);
+ TALLOC_FREE(state->ev);
+ }
+
+ TALLOC_FREE(mem_ctx);
+ poptFreeContext(pc);
+
+ return 0;
+}