From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH 2/7] Get rid of tuple_field_by_part_multikey Date: Wed, 8 May 2019 20:22:34 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: To: tarantool-patches@freelists.org List-ID: Always require multikey_idx to be passed to tuple_field_by_part. If the key definition isn't multikey, pass -1. Rationale: having separate functions for multikey and unikey indexes doesn't have any performance benefits (as all those functions are inline), but makes the code inconsistent with other functions (e.g. tuple_compare) which don't have a separate multikey variant. After all, passing -1 when the key definition is known to be unikey doesn't blow the code. While we are at it, let's also add a few assertions ensuring that the key definition isn't multikey to functions that don't support multikey yet. --- src/box/memtx_bitset.c | 6 ++--- src/box/memtx_rtree.c | 3 ++- src/box/tuple.h | 29 +++++++----------------- src/box/tuple_compare.cc | 53 +++++++++++++++++++++++--------------------- src/box/tuple_extract_key.cc | 12 +++++----- src/box/tuple_hash.cc | 17 ++++++++------ 6 files changed, 58 insertions(+), 62 deletions(-) diff --git a/src/box/memtx_bitset.c b/src/box/memtx_bitset.c index b6f8f7ac..275e736d 100644 --- a/src/box/memtx_bitset.c +++ b/src/box/memtx_bitset.c @@ -276,6 +276,7 @@ memtx_bitset_index_replace(struct index *base, struct tuple *old_tuple, struct memtx_bitset_index *index = (struct memtx_bitset_index *)base; assert(!base->def->opts.is_unique); + assert(!key_def_is_multikey(base->def->key_def)); assert(old_tuple != NULL || new_tuple != NULL); (void) mode; @@ -300,9 +301,8 @@ memtx_bitset_index_replace(struct index *base, struct tuple *old_tuple, } if (new_tuple != NULL) { - const char *field = - tuple_field_by_part(new_tuple, - base->def->key_def->parts); + const char *field = tuple_field_by_part(new_tuple, + base->def->key_def->parts, -1); uint32_t key_len; const void *key = make_key(field, &key_len); #ifndef OLD_GOOD_BITSET diff --git a/src/box/memtx_rtree.c b/src/box/memtx_rtree.c index 0a903517..19cb69a1 100644 --- a/src/box/memtx_rtree.c +++ b/src/box/memtx_rtree.c @@ -120,8 +120,9 @@ extract_rectangle(struct rtree_rect *rect, struct tuple *tuple, struct index_def *index_def) { assert(index_def->key_def->part_count == 1); + assert(!key_def_is_multikey(index_def->key_def)); const char *elems = tuple_field_by_part(tuple, - index_def->key_def->parts); + index_def->key_def->parts, -1); unsigned dimension = index_def->opts.dimension; uint32_t count = mp_decode_array(&elems); return mp_decode_rect(rect, dimension, elems, count, "Field"); diff --git a/src/box/tuple.h b/src/box/tuple.h index c0d06dbe..2a46f371 100644 --- a/src/box/tuple.h +++ b/src/box/tuple.h @@ -653,9 +653,9 @@ tuple_field_raw_by_full_path(struct tuple_format *format, const char *tuple, * @retval Field data if the field exists or NULL. */ static inline const char * -tuple_field_raw_by_part_multikey(struct tuple_format *format, const char *data, - const uint32_t *field_map, - struct key_part *part, int multikey_idx) +tuple_field_raw_by_part(struct tuple_format *format, const char *data, + const uint32_t *field_map, + struct key_part *part, int multikey_idx) { if (unlikely(part->format_epoch != format->epoch)) { assert(format->epoch != 0); @@ -672,32 +672,19 @@ tuple_field_raw_by_part_multikey(struct tuple_format *format, const char *data, } /** - * Get a tuple field pointed to by an index part. - * @param format Tuple format. - * @param data A pointer to MessagePack array. - * @param field_map A pointer to the LAST element of field map. - * @param part Index part to use. - * @retval Field data if the field exists or NULL. - */ -static inline const char * -tuple_field_raw_by_part(struct tuple_format *format, const char *data, - const uint32_t *field_map, struct key_part *part) -{ - return tuple_field_raw_by_part_multikey(format, data, field_map, - part, -1); -} - -/** * Get a field refereed by index @part in tuple. * @param tuple Tuple to get the field from. * @param part Index part to use. + * @param multikey_idx A multikey index hint. * @retval Field data if the field exists or NULL. */ static inline const char * -tuple_field_by_part(struct tuple *tuple, struct key_part *part) +tuple_field_by_part(struct tuple *tuple, struct key_part *part, + int multikey_idx) { return tuple_field_raw_by_part(tuple_format(tuple), tuple_data(tuple), - tuple_field_map(tuple), part); + tuple_field_map(tuple), part, + multikey_idx); } /** diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc index 9a3780c6..0aa032af 100644 --- a/src/box/tuple_compare.cc +++ b/src/box/tuple_compare.cc @@ -504,17 +504,17 @@ tuple_compare_slowpath(struct tuple *tuple_a, hint_t tuple_a_hint, for (; part < end; part++) { if (is_multikey) { - field_a = tuple_field_raw_by_part_multikey(format_a, - tuple_a_raw, field_map_a, part, - (int)tuple_a_hint); - field_b = tuple_field_raw_by_part_multikey(format_b, - tuple_b_raw, field_map_b, part, - (int)tuple_b_hint); + field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, + field_map_a, part, + (int)tuple_a_hint); + field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, + field_map_b, part, + (int)tuple_b_hint); } else if (has_json_paths) { field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, - field_map_a, part); + field_map_a, part, -1); field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, - field_map_b, part); + field_map_b, part, -1); } else { field_a = tuple_field_raw(format_a, tuple_a_raw, field_map_a, part->fieldno); @@ -568,17 +568,17 @@ tuple_compare_slowpath(struct tuple *tuple_a, hint_t tuple_a_hint, end = key_def->parts + key_def->part_count; for (; part < end; ++part) { if (is_multikey) { - field_a = tuple_field_raw_by_part_multikey(format_a, - tuple_a_raw, field_map_a, part, - (int)tuple_a_hint); - field_b = tuple_field_raw_by_part_multikey(format_b, - tuple_b_raw, field_map_b, part, - (int)tuple_b_hint); + field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, + field_map_a, part, + (int)tuple_a_hint); + field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, + field_map_b, part, + (int)tuple_b_hint); } else if (has_json_paths) { field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, - field_map_a, part); + field_map_a, part, -1); field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, - field_map_b, part); + field_map_b, part, -1); } else { field_a = tuple_field_raw(format_a, tuple_a_raw, field_map_a, part->fieldno); @@ -625,12 +625,12 @@ tuple_compare_with_key_slowpath(struct tuple *tuple, hint_t tuple_hint, if (likely(part_count == 1)) { const char *field; if (is_multikey) { - field = tuple_field_raw_by_part_multikey(format, - tuple_raw, field_map, part, - (int)tuple_hint); + field = tuple_field_raw_by_part(format, tuple_raw, + field_map, part, + (int)tuple_hint); } else if (has_json_paths) { field = tuple_field_raw_by_part(format, tuple_raw, - field_map, part); + field_map, part, -1); } else { field = tuple_field_raw(format, tuple_raw, field_map, part->fieldno); @@ -659,12 +659,12 @@ tuple_compare_with_key_slowpath(struct tuple *tuple, hint_t tuple_hint, for (; part < end; ++part, mp_next(&key)) { const char *field; if (is_multikey) { - field = tuple_field_raw_by_part_multikey(format, - tuple_raw, field_map, part, - (int)tuple_hint); + field = tuple_field_raw_by_part(format, tuple_raw, + field_map, part, + (int)tuple_hint); } else if (has_json_paths) { field = tuple_field_raw_by_part(format, tuple_raw, - field_map, part); + field_map, part, -1); } else { field = tuple_field_raw(format, tuple_raw, field_map, part->fieldno); @@ -1553,6 +1553,7 @@ template static hint_t key_hint(const char *key, uint32_t part_count, struct key_def *key_def) { + assert(!key_def_is_multikey(key_def)); if (part_count == 0) return HINT_NONE; return field_hint(key, key_def->parts->coll); @@ -1562,7 +1563,8 @@ template static hint_t tuple_hint(struct tuple *tuple, struct key_def *key_def) { - const char *field = tuple_field_by_part(tuple, key_def->parts); + assert(!key_def_is_multikey(key_def)); + const char *field = tuple_field_by_part(tuple, key_def->parts, -1); if (is_nullable && field == NULL) return hint_nil(); return field_hint(field, key_def->parts->coll); @@ -1584,6 +1586,7 @@ key_hint_multikey(const char *key, uint32_t part_count, struct key_def *key_def) * do nothing on key hint calculation an it is valid * because it is never used(unlike tuple hint). */ + assert(key_def_is_multikey(key_def)); return HINT_NONE; } diff --git a/src/box/tuple_extract_key.cc b/src/box/tuple_extract_key.cc index 7fded038..7868378d 100644 --- a/src/box/tuple_extract_key.cc +++ b/src/box/tuple_extract_key.cc @@ -132,7 +132,7 @@ tuple_extract_key_slowpath(struct tuple *tuple, struct key_def *key_def, key_def->parts[i].fieldno); } else { field = tuple_field_raw_by_part(format, data, field_map, - &key_def->parts[i]); + &key_def->parts[i], -1); } if (has_optional_parts && field == NULL) { bsize += mp_sizeof_nil(); @@ -179,7 +179,7 @@ tuple_extract_key_slowpath(struct tuple *tuple, struct key_def *key_def, key_def->parts[i].fieldno); } else { field = tuple_field_raw_by_part(format, data, field_map, - &key_def->parts[i]); + &key_def->parts[i], -1); } if (has_optional_parts && field == NULL) { key_buf = mp_encode_nil(key_buf); @@ -413,13 +413,14 @@ key_def_set_extract_func(struct key_def *key_def) bool tuple_key_contains_null(struct tuple *tuple, struct key_def *def) { + assert(!key_def_is_multikey(def)); struct tuple_format *format = tuple_format(tuple); const char *data = tuple_data(tuple); const uint32_t *field_map = tuple_field_map(tuple); for (struct key_part *part = def->parts, *end = part + def->part_count; part < end; ++part) { - const char *field = - tuple_field_raw_by_part(format, data, field_map, part); + const char *field = tuple_field_raw_by_part(format, data, + field_map, part, -1); if (field == NULL || mp_typeof(*field) == MP_NIL) return true; } @@ -429,9 +430,10 @@ tuple_key_contains_null(struct tuple *tuple, struct key_def *def) int tuple_validate_key_parts(struct key_def *key_def, struct tuple *tuple) { + assert(!key_def_is_multikey(key_def)); for (uint32_t idx = 0; idx < key_def->part_count; idx++) { struct key_part *part = &key_def->parts[idx]; - const char *field = tuple_field_by_part(tuple, part); + const char *field = tuple_field_by_part(tuple, part, -1); if (field == NULL) { if (key_part_is_nullable(part)) continue; diff --git a/src/box/tuple_hash.cc b/src/box/tuple_hash.cc index 85095eb8..63de2bae 100644 --- a/src/box/tuple_hash.cc +++ b/src/box/tuple_hash.cc @@ -155,11 +155,12 @@ struct TupleHash { static uint32_t hash(struct tuple *tuple, struct key_def *key_def) { + assert(!key_def_is_multikey(key_def)); uint32_t h = HASH_SEED; uint32_t carry = 0; uint32_t total_size = 0; - const char *field = - tuple_field_by_part(tuple, key_def->parts); + const char *field = tuple_field_by_part(tuple, + key_def->parts, -1); TupleFieldHash:: hash(&field, &h, &carry, &total_size); return PMurHash32_Result(h, carry, total_size); @@ -170,8 +171,9 @@ template <> struct TupleHash { static uint32_t hash(struct tuple *tuple, struct key_def *key_def) { - const char *field = - tuple_field_by_part(tuple, key_def->parts); + assert(!key_def_is_multikey(key_def)); + const char *field = tuple_field_by_part(tuple, + key_def->parts, -1); uint64_t val = mp_decode_uint(&field); if (likely(val <= UINT32_MAX)) return val; @@ -348,7 +350,7 @@ uint32_t tuple_hash_key_part(uint32_t *ph1, uint32_t *pcarry, struct tuple *tuple, struct key_part *part) { - const char *field = tuple_field_by_part(tuple, part); + const char *field = tuple_field_by_part(tuple, part, -1); if (field == NULL) return tuple_hash_null(ph1, pcarry); return tuple_hash_field(ph1, pcarry, &field, part->coll); @@ -360,6 +362,7 @@ tuple_hash_slowpath(struct tuple *tuple, struct key_def *key_def) { assert(has_json_paths == key_def->has_json_paths); assert(has_optional_parts == key_def->has_optional_parts); + assert(!key_def_is_multikey(key_def)); uint32_t h = HASH_SEED; uint32_t carry = 0; uint32_t total_size = 0; @@ -370,7 +373,7 @@ tuple_hash_slowpath(struct tuple *tuple, struct key_def *key_def) const char *field; if (has_json_paths) { field = tuple_field_raw_by_part(format, tuple_raw, field_map, - key_def->parts); + key_def->parts, -1); } else { field = tuple_field_raw(format, tuple_raw, field_map, prev_fieldno); @@ -391,7 +394,7 @@ tuple_hash_slowpath(struct tuple *tuple, struct key_def *key_def) struct key_part *part = &key_def->parts[part_id]; if (has_json_paths) { field = tuple_field_raw_by_part(format, tuple_raw, - field_map, part); + field_map, part, -1); } else { field = tuple_field_raw(format, tuple_raw, field_map, part->fieldno); -- 2.11.0