From 55e3bb3b9202bcec83dec59d6a08ff4a793f99c8 Mon Sep 17 00:00:00 2001 From: Vladimir Davydov <vdavydov@tarantool.org> Date: Tue, 25 Oct 2022 15:27:17 +0300 Subject: [PATCH] memtx: add option to disable decompression of read view tuples We need this option to implement a basic MT-safe read view C API in the EE repository. Closes #7815 NO_DOC=internal NO_CHANGELOG=internal NO_TEST=will be added to the EE repository --- src/box/index.h | 18 ++++++++++++------ src/box/memtx_engine.cc | 9 +++++++-- src/box/memtx_engine.h | 16 +++++++++++----- src/box/memtx_hash.cc | 5 ++++- src/box/memtx_tree.cc | 5 ++++- src/box/read_view.c | 1 + src/box/read_view.h | 9 +++++++++ 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/box/index.h b/src/box/index.h index dc5f4084d9..32545cdcf3 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -642,9 +642,12 @@ struct index_read_view_vtab { * Look up a tuple by a full key in a read view. * * The tuple data and size are returned in the data and size arguments. - * Note, the tuple may be allocated from the fiber region so one should - * call region_truncate after using the data. If the key isn't found, - * the data is set to NULL. + * If the key isn't found, the data is set to NULL. + * + * Note, unless the read_view_opts::disable_decompression flag was set + * at read_view_open, the returned data may be allocated on the fiber + * region, and the user is supposed to call region_truncate after using + * the data. * * Returns 0 on success. On error returns -1 and sets diag. */ @@ -685,9 +688,12 @@ struct index_read_view_iterator_base { * Iterate to the next tuple in the read view. * * The tuple data and size are returned in the data and size arguments. - * Note, the tuple may be allocated from the fiber region so one should - * call region_truncate after using the data. On EOF the data is set to - * NULL. + * On EOF the data is set to NULL. + * + * Note, unless the read_view_opts::disable_decompression flag was set + * at read_view_open, the returned data may be allocated on the fiber + * region, and the user is supposed to call region_truncate after using + * the data. * * Returns 0 on success. On error returns -1 and sets diag. */ diff --git a/src/box/memtx_engine.cc b/src/box/memtx_engine.cc index 64c7e0c03c..faca74651f 100644 --- a/src/box/memtx_engine.cc +++ b/src/box/memtx_engine.cc @@ -1652,6 +1652,7 @@ memtx_prepare_result_tuple(struct tuple **result) int memtx_prepare_read_view_tuple(struct tuple *tuple, struct memtx_tx_snapshot_cleaner *cleaner, + bool disable_decompression, const char **data, uint32_t *size) { tuple = memtx_tx_snapshot_clarify(cleaner, tuple); @@ -1661,8 +1662,12 @@ memtx_prepare_read_view_tuple(struct tuple *tuple, return 0; } *data = tuple_data_range(tuple, size); - *data = memtx_tuple_decompress_raw(*data, *data + *size, size); - return *data == NULL ? -1 : 0; + if (!disable_decompression) { + *data = memtx_tuple_decompress_raw(*data, *data + *size, size); + if (*data == NULL) + return -1; + } + return 0; } int diff --git a/src/box/memtx_engine.h b/src/box/memtx_engine.h index dd5ddcc856..2fbc746857 100644 --- a/src/box/memtx_engine.h +++ b/src/box/memtx_engine.h @@ -284,17 +284,23 @@ memtx_prepare_result_tuple(struct tuple **result); * to the user. * * A pointer to the raw tuple data and its size are returned in the data and - * size out argument. The data may be allocated from the fiber region (e.g. if - * the original tuple is compressed) so the caller should clean up the region - * after using the data. If the tuple should be skipped (e.g. it's not visible - * from the read view, because it was dirty when the read view was created), - * the data is set to NULL. + * size out argument. + * + * This function performs two tasks: + * + * 1. Eliminates dirty tuples using the provided snapshot cleaner created + * at read_view_open. If the given tuple should be skipped, the data is + * set to NULL. + * + * 2. Decompresses tuples if required, unless the disable_decompression flag + * is set. Decompressed tuple data is stored on the fiber region. * * Returns 0 on success. On error returns -1 and sets diag. */ int memtx_prepare_read_view_tuple(struct tuple *tuple, struct memtx_tx_snapshot_cleaner *cleaner, + bool disable_decompression, const char **data, uint32_t *size); /** diff --git a/src/box/memtx_hash.cc b/src/box/memtx_hash.cc index f057ee53f3..23aab5584c 100644 --- a/src/box/memtx_hash.cc +++ b/src/box/memtx_hash.cc @@ -512,6 +512,8 @@ struct hash_read_view { struct light_index_view view; /** Used for clarifying read view tuples. */ struct memtx_tx_snapshot_cleaner cleaner; + /** See read_view_opts::disable_decompression. */ + bool disable_decompression; }; /** Read view iterator implementation. */ @@ -573,6 +575,7 @@ hash_read_view_iterator_next_raw(struct index_read_view_iterator *iterator, return 0; } if (memtx_prepare_read_view_tuple(*res, &rv->cleaner, + rv->disable_decompression, data, size) != 0) return -1; if (*data != NULL) @@ -628,7 +631,6 @@ static struct index_read_view * memtx_hash_index_create_read_view(struct index *base, const struct read_view_opts *opts) { - (void)opts; static const struct index_read_view_vtab vtab = { .free = hash_read_view_free, .get_raw = hash_read_view_get_raw, @@ -643,6 +645,7 @@ memtx_hash_index_create_read_view(struct index *base, } struct space *space = space_cache_find(base->def->space_id); memtx_tx_snapshot_cleaner_create(&rv->cleaner, space); + rv->disable_decompression = opts->disable_decompression; rv->index = index; index_ref(base); light_index_view_create(&rv->view, &index->hash_table); diff --git a/src/box/memtx_tree.cc b/src/box/memtx_tree.cc index ccaeca70da..c9e73bd550 100644 --- a/src/box/memtx_tree.cc +++ b/src/box/memtx_tree.cc @@ -1851,6 +1851,8 @@ struct tree_read_view { memtx_tree_view_t<USE_HINT> tree_view; /** Used for clarifying read view tuples. */ struct memtx_tx_snapshot_cleaner cleaner; + /** See read_view_opts::disable_decompression. */ + bool disable_decompression; }; /** Read view iterator implementation. */ @@ -1929,6 +1931,7 @@ tree_read_view_iterator_next_raw(struct index_read_view_iterator *iterator, memtx_tree_view_iterator_next(&rv->tree_view, &it->tree_iterator); if (memtx_prepare_read_view_tuple(res->tuple, &rv->cleaner, + rv->disable_decompression, data, size) != 0) return -1; if (*data != NULL) @@ -1991,7 +1994,6 @@ static struct index_read_view * memtx_tree_index_create_read_view(struct index *base, const struct read_view_opts *opts) { - (void)opts; static const struct index_read_view_vtab vtab = { .free = tree_read_view_free<USE_HINT>, .get_raw = tree_read_view_get_raw<USE_HINT>, @@ -2007,6 +2009,7 @@ memtx_tree_index_create_read_view(struct index *base, } struct space *space = space_cache_find(base->def->space_id); memtx_tx_snapshot_cleaner_create(&rv->cleaner, space); + rv->disable_decompression = opts->disable_decompression; rv->index = index; index_ref(base); memtx_tree_view_create(&rv->tree_view, &index->tree); diff --git a/src/box/read_view.c b/src/box/read_view.c index 43d553cba6..0ead9cf951 100644 --- a/src/box/read_view.c +++ b/src/box/read_view.c @@ -49,6 +49,7 @@ read_view_opts_create(struct read_view_opts *opts) opts->enable_field_names = false; opts->enable_space_upgrade = false; opts->enable_temporary_spaces = false; + opts->disable_decompression = false; } static void diff --git a/src/box/read_view.h b/src/box/read_view.h index 998e990095..ce562beb07 100644 --- a/src/box/read_view.h +++ b/src/box/read_view.h @@ -140,6 +140,15 @@ struct read_view_opts { * flag is set. */ bool enable_temporary_spaces; + /** + * Memtx-specific. Disables decompression of tuples fetched from + * the read view. Setting this flag makes the raw read view methods + * (get_raw, next_raw) return a pointer to the data stored in + * the read view as is, without any preprocessing or copying to + * the fiber region. The user is supposed to decompress the data + * encoded in the MP_COMPRESSION MsgPack extension manually. + */ + bool disable_decompression; }; /** Sets read view options to default values. */ -- GitLab