Skip to content

Commit

Permalink
tuple: in attempt to be more merge-compatible with 1.8, move code around
Browse files Browse the repository at this point in the history
Move the ANY index type to tuple_compare.cc to simplify merges with 1.8.
Remove dead code.

Collateral: fix a release mode warning in vinyl.
  • Loading branch information
kostja committed Sep 27, 2016
1 parent e1e5d4a commit e5f67b9
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 279 deletions.
264 changes: 0 additions & 264 deletions src/box/tuple.cc
Expand Up @@ -282,12 +282,6 @@ tuple_next_cstr(struct tuple_iterator *it)
return tuple_field_to_cstr(str, len);
}

extern inline const char *
tuple_field(const struct tuple *tuple, uint32_t i);

extern inline uint32_t
tuple_field_u32(struct tuple *tuple, uint32_t i);

const char *
tuple_field_cstr(struct tuple *tuple, uint32_t i)
{
Expand Down Expand Up @@ -398,264 +392,6 @@ tuple_new(struct tuple_format *format, const char *data, const char *end)
return new_tuple;
}

/*
* Compare two tuple fields.
* Separate version exists since compare is a very
* often used operation, so any performance speed up
* in it can have dramatic impact on the overall
* server performance.
*/
inline __attribute__((always_inline)) int
mp_compare_uint(const char **data_a, const char **data_b);

enum mp_class {
MP_CLASS_NIL = 0,
MP_CLASS_BOOL,
MP_CLASS_NUMBER,
MP_CLASS_STR,
MP_CLASS_BIN,
MP_CLASS_ARRAY,
MP_CLASS_MAP
};

static enum mp_class mp_classes[] = {
/* .MP_NIL = */ MP_CLASS_NIL,
/* .MP_UINT = */ MP_CLASS_NUMBER,
/* .MP_INT = */ MP_CLASS_NUMBER,
/* .MP_STR = */ MP_CLASS_STR,
/* .MP_BIN = */ MP_CLASS_BIN,
/* .MP_ARRAY = */ MP_CLASS_ARRAY,
/* .MP_MAP = */ MP_CLASS_MAP,
/* .MP_BOOL = */ MP_CLASS_BOOL,
/* .MP_FLOAT = */ MP_CLASS_NUMBER,
/* .MP_DOUBLE = */ MP_CLASS_NUMBER,
/* .MP_BIN = */ MP_CLASS_BIN
};

#define COMPARE_RESULT(a, b) (a < b ? -1 : a > b)

static enum mp_class
mp_classof(enum mp_type type)
{
return mp_classes[type];
}

static inline double
mp_decode_number(const char **data)
{
double val;
switch (mp_typeof(**data)) {
case MP_UINT:
val = mp_decode_uint(data);
break;
case MP_INT:
val = mp_decode_int(data);
break;
case MP_FLOAT:
val = mp_decode_float(data);
break;
case MP_DOUBLE:
val = mp_decode_double(data);
break;
default:
unreachable();
}
return val;
}

static int
mp_compare_bool(const char *field_a, const char *field_b)
{
int a_val = mp_decode_bool(&field_a);
int b_val = mp_decode_bool(&field_b);
return COMPARE_RESULT(a_val, b_val);
}

static int
mp_compare_integer(const char *field_a, const char *field_b)
{
enum mp_type a_type = mp_typeof(*field_a);
enum mp_type b_type = mp_typeof(*field_b);
assert(mp_classof(a_type) == MP_CLASS_NUMBER);
assert(mp_classof(b_type) == MP_CLASS_NUMBER);
if (a_type == MP_UINT) {
uint64_t a_val = mp_decode_uint(&field_a);
if (b_type == MP_UINT) {
uint64_t b_val = mp_decode_uint(&field_b);
return COMPARE_RESULT(a_val, b_val);
} else {
int64_t b_val = mp_decode_int(&field_b);
if (b_val < 0)
return 1;
return COMPARE_RESULT(a_val, (uint64_t)b_val);
}
} else {
int64_t a_val = mp_decode_int(&field_a);
if (b_type == MP_UINT) {
uint64_t b_val = mp_decode_uint(&field_b);
if (a_val < 0)
return -1;
return COMPARE_RESULT((uint64_t)a_val, b_val);
} else {
int64_t b_val = mp_decode_int(&field_b);
return COMPARE_RESULT(a_val, b_val);
}
}
}

static int
mp_compare_number(const char *field_a, const char *field_b)
{
enum mp_type a_type = mp_typeof(*field_a);
enum mp_type b_type = mp_typeof(*field_b);
assert(mp_classof(a_type) == MP_CLASS_NUMBER);
assert(mp_classof(b_type) == MP_CLASS_NUMBER);
if (a_type == MP_FLOAT || a_type == MP_DOUBLE ||
b_type == MP_FLOAT || b_type == MP_DOUBLE) {
double a_val = mp_decode_number(&field_a);
double b_val = mp_decode_number(&field_b);
return COMPARE_RESULT(a_val, b_val);
}
return mp_compare_integer(field_a, field_b);
}

static inline int
mp_compare_str(const char *field_a, const char *field_b)
{
uint32_t size_a = mp_decode_strl(&field_a);
uint32_t size_b = mp_decode_strl(&field_b);
int r = memcmp(field_a, field_b, MIN(size_a, size_b));
if (r != 0)
return r;
return COMPARE_RESULT(size_a, size_b);
}

static inline int
mp_compare_bin(const char *field_a, const char *field_b)
{
uint32_t size_a = mp_decode_binl(&field_a);
uint32_t size_b = mp_decode_binl(&field_b);
int r = memcmp(field_a, field_b, MIN(size_a, size_b));
if (r != 0)
return r;
return COMPARE_RESULT(size_a, size_b);
}

typedef int (*mp_compare_f)(const char *, const char *);
static mp_compare_f mp_class_comparators[] = {
/* .MP_CLASS_NIL = */ NULL,
/* .MP_CLASS_BOOL = */ mp_compare_bool,
/* .MP_CLASS_NUMBER = */ mp_compare_number,
/* .MP_CLASS_STR = */ mp_compare_str,
/* .MP_CLASS_BIN = */ mp_compare_bin,
/* .MP_CLASS_ARRAY = */ NULL,
/* .MP_CLASS_MAP = */ NULL,
};

static int
mp_compare_scalar(const char *field_a, const char *field_b)
{
enum mp_type a_type = mp_typeof(*field_a);
enum mp_type b_type = mp_typeof(*field_b);
enum mp_class a_class = mp_classof(a_type);
enum mp_class b_class = mp_classof(b_type);
if (a_class != b_class)
return COMPARE_RESULT(a_class, b_class);
mp_compare_f cmp = mp_class_comparators[a_class];
assert(cmp != NULL);
return cmp(field_a, field_b);
}

int
tuple_compare_field(const char *field_a, const char *field_b,
enum field_type type)
{
switch (type) {
case FIELD_TYPE_UNSIGNED:
return mp_compare_uint(field_a, field_b);
case FIELD_TYPE_STRING:
return mp_compare_str(field_a, field_b);
case FIELD_TYPE_INTEGER:
return mp_compare_integer(field_a, field_b);
case FIELD_TYPE_NUMBER:
return mp_compare_number(field_a, field_b);
case FIELD_TYPE_SCALAR:
return mp_compare_scalar(field_a, field_b);
default:
unreachable();
return 0;
}
}

int
tuple_compare_default(const struct tuple *tuple_a, const struct tuple *tuple_b,
const struct key_def *key_def)
{
if (key_def->part_count == 1 && key_def->parts[0].fieldno == 0) {
const char *a = tuple_a->data;
const char *b = tuple_b->data;
mp_decode_array(&a);
mp_decode_array(&b);
return tuple_compare_field(a, b, key_def->parts[0].type);
}

const struct key_part *part = key_def->parts;
const struct key_part *end = part + key_def->part_count;
struct tuple_format *format_a = tuple_format(tuple_a);
struct tuple_format *format_b = tuple_format(tuple_b);
const char *field_a;
const char *field_b;
int r = 0;

for (; part < end; part++) {
field_a = tuple_field_old(format_a, tuple_a, part->fieldno);
field_b = tuple_field_old(format_b, tuple_b, part->fieldno);
assert(field_a != NULL && field_b != NULL);
if ((r = tuple_compare_field(field_a, field_b, part->type)))
break;
}
return r;
}

int
tuple_compare_dup(const struct tuple *tuple_a, const struct tuple *tuple_b,
const struct key_def *key_def)
{
int r = key_def->tuple_compare(tuple_a, tuple_b, key_def);
if (r == 0)
r = tuple_a < tuple_b ? -1 : tuple_a > tuple_b;

return r;
}

int
tuple_compare_with_key_default(const struct tuple *tuple, const char *key,
uint32_t part_count, const struct key_def *key_def)
{
assert(key != NULL || part_count == 0);
assert(part_count <= key_def->part_count);
struct tuple_format *format = tuple_format(tuple);
if (likely(part_count == 1)) {
const struct key_part *part = key_def->parts;
const char *field = tuple_field_old(format, tuple,
part->fieldno);
return tuple_compare_field(field, key, part->type);
}

const struct key_part *part = key_def->parts;
const struct key_part *end = part + MIN(part_count, key_def->part_count);
int r = 0; /* Part count can be 0 in wildcard searches. */
for (; part < end; part++) {
const char *field = tuple_field_old(format, tuple,
part->fieldno);
r = tuple_compare_field(field, key, part->type);
if (r != 0)
break;
mp_next(&key);
}
return r;
}

void
tuple_init(float tuple_arena_max_size, uint32_t objsize_min,
uint32_t objsize_max, float alloc_factor)
Expand Down
14 changes: 0 additions & 14 deletions src/box/tuple.h
Expand Up @@ -683,20 +683,6 @@ int
tuple_compare_default(const struct tuple *tuple_a, const struct tuple *tuple_b,
const struct key_def *key_def);

/**
* @brief Compare two tuples field by field for duplicate using key definition
* @param tuple_a tuple
* @param tuple_b tuple
* @param key_def key definition
* @retval 0 if key_fields(tuple_a) == key_fields(tuple_b) and
* tuple_a == tuple_b - tuple_a is the same object as tuple_b
* @retval <0 if key_fields(tuple_a) <= key_fields(tuple_b)
* @retval >0 if key_fields(tuple_a > key_fields(tuple_b)
*/
int
tuple_compare_dup(const struct tuple *tuple_a, const struct tuple *tuple_b,
const struct key_def *key_def);

/**
* @brief Compare a tuple with a key field by field using key definition
* @param tuple_a tuple
Expand Down

0 comments on commit e5f67b9

Please sign in to comment.