diff options
Diffstat (limited to 'source3/utils/async-tracker.c')
-rw-r--r-- | source3/utils/async-tracker.c | 315 |
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; +} |