diff --git a/src/box/index.h b/src/box/index.h index dc5f4084d9b7f484fd169fde2e92dc9ea6a1e845..32545cdcf3afd73973377f48028e3cfa7c4aa427 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 64c7e0c03ca6554b023609408c95e8fc6cf99d36..faca74651fff09b70dfc09cac71fe25a8dad27fd 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 dd5ddcc8560db446b35fe300d949648172fc3f06..2fbc7468573dbff6f8f17558aa21ecb03bcd36bf 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 f057ee53f3e0454180fc1edf52e415f42df97e6a..23aab5584c8e22bf48358dc26e5bd5f8c09f8a1a 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 ccaeca70da99fa74166591c442f459756c057a41..c9e73bd550c6a01f3f1d3341b9465ebc186bbf8b 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 43d553cba684e0a312713559af253ef1d821d91a..0ead9cf95196f6e83ba51f2d2ac551845bc6f951 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 998e990095fd1e558891a1598b8a989fc43e7667..ce562beb07a9f49789b76c971d37d6543a932e81 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. */