From: Vladimir Davydov <vdavydov.dev@gmail.com>
To: tarantool-patches@freelists.org
Subject: [PATCH 2/7] Get rid of tuple_field_by_part_multikey
Date: Wed, 8 May 2019 20:22:34 +0300 [thread overview]
Message-ID: <dace384936707d09522a2df6d5c623d081fdcf23.1557334828.git.vdavydov.dev@gmail.com> (raw)
In-Reply-To: <cover.1557334828.git.vdavydov.dev@gmail.com>
In-Reply-To: <cover.1557334828.git.vdavydov.dev@gmail.com>
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 +++++++++++++++++++++++---------------------
| 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 <enum field_type type, bool is_nullable>
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<type, is_nullable>(key, key_def->parts->coll);
@@ -1562,7 +1563,8 @@ template <enum field_type type, bool is_nullable>
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<type, is_nullable>(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;
}
--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<TYPE, MORE_TYPES...>::
hash(&field, &h, &carry, &total_size);
return PMurHash32_Result(h, carry, total_size);
@@ -170,8 +171,9 @@ template <>
struct TupleHash<FIELD_TYPE_UNSIGNED> {
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
next prev parent reply other threads:[~2019-05-08 17:22 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-08 17:22 [PATCH 0/7] Support multikey indexes in Vinyl Vladimir Davydov
2019-05-08 17:22 ` [PATCH 1/7] Make tuple comparison hints mandatory Vladimir Davydov
2019-05-09 5:58 ` [tarantool-patches] " Konstantin Osipov
2019-05-08 17:22 ` Vladimir Davydov [this message]
2019-05-08 17:22 ` [PATCH 3/7] Make tuple_extract_key support multikey indexes Vladimir Davydov
2019-05-08 17:22 ` [PATCH 4/7] Make tuple_bloom " Vladimir Davydov
2019-05-08 17:22 ` [PATCH 5/7] vinyl: use field_map_builder for constructing stmt field map Vladimir Davydov
2019-05-08 17:22 ` [PATCH 6/7] vinyl: use multikey hints while writing runs Vladimir Davydov
2019-05-08 17:22 ` [PATCH 7/7] vinyl: implement multikey index support Vladimir Davydov
2019-05-13 16:34 ` [PATCH] Use MULTIKEY_NONE instead of -1 Vladimir Davydov
2019-05-13 19:26 ` [PATCH 0/7] Support multikey indexes in Vinyl Vladimir Davydov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=dace384936707d09522a2df6d5c623d081fdcf23.1557334828.git.vdavydov.dev@gmail.com \
--to=vdavydov.dev@gmail.com \
--cc=tarantool-patches@freelists.org \
--subject='Re: [PATCH 2/7] Get rid of tuple_field_by_part_multikey' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox