From 08070d45c5905e6afa1c011c312e304605563580 Mon Sep 17 00:00:00 2001 From: Vladimir Davydov <vdavydov@tarantool.org> Date: Mon, 29 Aug 2022 14:35:59 +0300 Subject: [PATCH] read_view: add tuple_format to space_read_view To support accessing tuple fields by name, we create a runtime tuple format for each space read view, using the space field names to initialize the field dictionary. Note, we can't reuse the space tuple format as is, because it allocates tuples from the engine arena, which is single-threaded, while a read view may be used from any thread, not just tx. The runtime arena is single-threaded as well, but we will make it per-thread in future. Note, we can't even reuse tuple field dictionary - we create a new one using the space definition instead - because the dictionary is in fact mutable - it may be changed when the space definition is altered, see tuple_dictionary_swap. Good news is runtime tuple formats are reusable so if we create several read views of the same space, they will all use the same tuple format. Since this feature isn't required for snapshots/replication, we add a read view option to enable it - read_view_opts::needs_field_names. Needed for https://github.com/tarantool/tarantool-ee/issues/207 NO_DOC=internal NO_TEST=ee NO_CHANGELOG=internal --- src/box/read_view.c | 23 +++++++++++++++++++++++ src/box/read_view.h | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/box/read_view.c b/src/box/read_view.c index c99a1ea34e..819863224d 100644 --- a/src/box/read_view.c +++ b/src/box/read_view.c @@ -18,6 +18,7 @@ #include "space.h" #include "space_cache.h" #include "trivia/util.h" +#include "tuple.h" static bool default_space_filter(struct space *space, void *arg) @@ -42,6 +43,7 @@ read_view_opts_create(struct read_view_opts *opts) opts->filter_space = default_space_filter; opts->filter_index = default_index_filter; opts->filter_arg = NULL; + opts->needs_field_names = false; } static void @@ -54,6 +56,7 @@ space_read_view_delete(struct space_read_view *space_rv) index_read_view_delete(index_rv); } } + tuple_format_unref(space_rv->format); TRASH(space_rv); free(space_rv); } @@ -61,6 +64,24 @@ space_read_view_delete(struct space_read_view *space_rv) static struct space_read_view * space_read_view_new(struct space *space, const struct read_view_opts *opts) { + struct tuple_format *format = tuple_format_runtime; + if (opts->needs_field_names) { + /** + * Sic: Even though a tuple dictionary has a reference counter, + * we can't reuse the tuple dictionary used by the space tuple + * format, because it may change when the space is altered, see + * tuple_dictionary_swap. + */ + struct tuple_dictionary *dict = tuple_dictionary_new( + space->def->fields, space->def->field_count); + if (dict == NULL) + return NULL; + format = runtime_tuple_format_new(dict); + tuple_dictionary_unref(dict); + if (format == NULL) + return NULL; + } + struct space_read_view *space_rv; size_t index_map_size = sizeof(*space_rv->index_map) * (space->index_id_max + 1); @@ -76,6 +97,8 @@ space_read_view_new(struct space *space, const struct read_view_opts *opts) space_rv->id = space_id(space); space_rv->group_id = space_group_id(space); + space_rv->format = format; + tuple_format_ref(format); space_rv->index_id_max = space->index_id_max; memset(space_rv->index_map, 0, index_map_size); for (uint32_t i = 0; i <= space->index_id_max; i++) { diff --git a/src/box/read_view.h b/src/box/read_view.h index d6aa859f5f..ab7f37f54a 100644 --- a/src/box/read_view.h +++ b/src/box/read_view.h @@ -27,6 +27,21 @@ struct space_read_view { uint32_t id; /** Space name. */ char *name; + /** + * Runtime tuple format needed to access tuple field names by name. + * Referenced (ref counter incremented). + * + * A new format is created only if read_view_opts::needs_field_names + * is set, otherwise runtime_tuple_format is used. + * + * We can't just use the space tuple format as is because it allocates + * tuples from the space engine arena, which is single-threaded, while + * a read view may be used from threads other than tx. Good news is + * runtime tuple formats are reusable so if we create more than one + * read view of the same space, we will use just one tuple format for + * them all. + */ + struct tuple_format *format; /** Replication group id. See space_opts::group_id. */ uint32_t group_id; /** @@ -81,6 +96,13 @@ struct read_view_opts { * Argument passed to filter functions. */ void *filter_arg; + /** + * If this flag is set, a new runtime tuple format will be created for + * each read view space to support accessing tuple fields by name, + * otherwise the preallocated name-less runtime tuple format will be + * used instead. + */ + bool needs_field_names; }; /** Sets read view options to default values. */ -- GitLab