From 50b794f17e8ea267277bcffa4c1859102a1803b4 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tsisyk.com>
Date: Thu, 22 Nov 2012 18:54:25 +0400
Subject: [PATCH] Update tarantool_checksum to use new mhash.h

---
 client/tarantool_checksum/mhash-val.h      | 443 ---------------------
 client/tarantool_checksum/tc_file.c        |  30 +-
 client/tarantool_checksum/tc_generate.c    |  29 +-
 client/tarantool_checksum/tc_hash.h        |  38 +-
 client/tarantool_checksum/tc_space.c       |  35 +-
 client/tarantool_checksum/tc_space.h       |   4 +-
 client/tarantool_checksum/tc_verify.c      |  16 +-
 client/tarantool_checksum/tnt_checksum.cbp | 221 ++++++++++
 8 files changed, 310 insertions(+), 506 deletions(-)
 delete mode 100644 client/tarantool_checksum/mhash-val.h
 create mode 100644 client/tarantool_checksum/tnt_checksum.cbp

diff --git a/client/tarantool_checksum/mhash-val.h b/client/tarantool_checksum/mhash-val.h
deleted file mode 100644
index e17ae60002..0000000000
--- a/client/tarantool_checksum/mhash-val.h
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/* The MIT License
-
-   Copyright (c) 2008, by Attractive Chaos <attractivechaos@aol.co.uk>
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   "Software"), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be
-   included in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-   SOFTWARE.
-*/
-
-#ifndef MH_INCREMENTAL_RESIZE
-#define MH_INCREMENTAL_RESIZE 1
-#endif
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <math.h>
-#include <string.h>
-
-#define mh_cat(a, b) mh##a##_##b
-#define mh_ecat(a, b) mh_cat(a, b)
-#define _mh(x) mh_ecat(mh_name, x)
-
-#define mh_unlikely(x)  __builtin_expect((x),0)
-
-#ifndef MH_TYPEDEFS
-#define MH_TYPEDEFS
-typedef uint32_t mh_int_t;
-#endif /* MH_TYPEDEFS */
-
-#ifndef __ac_HASH_PRIME_SIZE
-#define __ac_HASH_PRIME_SIZE 31
-static const mh_int_t __ac_prime_list[__ac_HASH_PRIME_SIZE] = {
-	3ul,		11ul,		23ul,		53ul,
-	97ul,		193ul,		389ul,		769ul,
-	1543ul,		3079ul,		6151ul,		12289ul,
-	24593ul,	49157ul,	98317ul,	196613ul,
-	393241ul,	786433ul,	1572869ul,	3145739ul,
-	6291469ul,	12582917ul,	25165843ul,	50331653ul,
-	100663319ul,	201326611ul,	402653189ul,	805306457ul,
-	1610612741ul,	3221225473ul,	4294967291ul
-};
-#endif /* __ac_HASH_PRIME_SIZE */
-
-#ifndef MH_HEADER
-#define MH_HEADER
-
-struct _mh(pair) {
-	mh_val_t val;
-};
-
-struct _mh(t) {
-	struct _mh(pair) * p;
-	mh_int_t *b;
-	mh_int_t n_buckets;
-	mh_int_t n_dirty;
-	mh_int_t size;
-	mh_int_t upper_bound;
-	mh_int_t prime;
-
-	mh_int_t resize_cnt;
-	mh_int_t resize_position;
-	mh_int_t batch;
-	struct _mh(t) *shadow;
-};
-
-#define mh_exist(h, i)		({ h->b[i >> 4] & (1 << (i % 16)); })
-#define mh_dirty(h, i)		({ h->b[i >> 4] & (1 << (i % 16 + 16)); })
-
-#define mh_setfree(h, i)	({ h->b[i >> 4] &= ~(1 << (i % 16)); })
-#define mh_setexist(h, i)	({ h->b[i >> 4] |= (1 << (i % 16)); })
-#define mh_setdirty(h, i)	({ h->b[i >> 4] |= (1 << (i % 16 + 16)); })
-
-#define mh_value(h, i)		(h)->p[(i)].val
-#define mh_size(h)		({ (h)->size;		})
-#define mh_capacity(h)		({ (h)->n_buckets;	})
-#define mh_begin(h)		({ 0;			})
-#define mh_end(h)		({ (h)->n_buckets;	})
-
-#define MH_DENSITY 0.7
-
-void _mh(init)(struct _mh(t) *h);
-void _mh(clear)(struct _mh(t) *h);
-void _mh(destroy)(struct _mh(t) *h);
-void _mh(resize)(mh_arg_t arg, struct _mh(t) *h);
-int _mh(start_resize)(mh_arg_t arg, struct _mh(t) *h, mh_int_t buckets, mh_int_t batch);
-void _mh(reserve)(mh_arg_t arg, struct _mh(t) *h, mh_int_t size);
-void __attribute__((noinline)) _mh(del_resize)(mh_arg_t arg, struct _mh(t) *h, mh_int_t x);
-void _mh(dump)(struct _mh(t) *h);
-
-#define put_slot(arg, h, key) _mh(put_slot)(arg, h, key)
-
-static inline mh_int_t
-_mh(next_slot)(mh_int_t slot, mh_int_t inc, mh_int_t size)
-{
-	slot += inc;
-	return slot >= size ? slot - size : slot;
-}
-
-static inline mh_int_t
-_mh(get)(mh_arg_t arg, struct _mh(t) *h, mh_val_t key)
-{
-	mh_int_t k = mh_hash(arg, key);
-	mh_int_t i = k % h->n_buckets;
-	mh_int_t inc = 1 + k % (h->n_buckets - 1);
-	for (;;) {
-		if ((mh_exist(h, i) && mh_eq(arg, key, h->p[i].val)))
-			return i;
-
-		if (!mh_dirty(h, i))
-			return h->n_buckets;
-
-		i = _mh(next_slot)(i, inc, h->n_buckets);
-	}
-}
-
-static inline mh_int_t
-_mh(put_slot)(mh_arg_t arg, struct _mh(t) *h, mh_val_t key)
-{
-	mh_int_t k = mh_hash(arg, key); /* hash key */
-	mh_int_t i = k % h->n_buckets; /* offset in the hash table. */
-	mh_int_t inc = 1 + k % (h->n_buckets - 1); /* overflow chain increment. */
-
-	/* Skip through all collisions. */
-	while (mh_exist(h, i)) {
-		if (mh_eq(arg, key, h->p[i].val))
-			return i;               /* Found a duplicate. */
-		/*
-		 * Mark this link as part of a collision chain. The
-		 * chain always ends with a non-marked link.
-		 * Note: the collision chain for this key may share
-		 * links with collision chains of other keys.
-		*/
-		mh_setdirty(h, i);
-		i = _mh(next_slot)(i, inc, h->n_buckets);
-	}
-	/*
-	 * Found an unused, but possibly dirty slot. Use it.
-	 * However, if this is a dirty slot, first check that
-	 * there are no duplicates down the collision chain. The
-	 * current link can also be from a collision chain of some
-	 * other key, but this is can't be established, so check
-	 * anyway.
-	 */
-	mh_int_t save_i = i;
-	while (mh_dirty(h, i)) {
-		i = _mh(next_slot)(i, inc, h->n_buckets);
-
-		if (mh_exist(h, i) && mh_eq(arg, key, h->p[i].val))
-			return i;               /* Found a duplicate. */
-	}
-	/* Reached the end of the collision chain: no duplicates. */
-	return save_i;
-}
-
-static inline mh_int_t
-_mh(put)(mh_arg_t arg, struct _mh(t) *h, mh_val_t val, int * ret)
-{
-	mh_int_t x = mh_end(h);
-	if (h->size == h->n_buckets)
-		/* no one free elements in the hash table */
-		goto put_done;
-
-#if MH_INCREMENTAL_RESIZE
-	if (mh_unlikely(h->resize_position > 0))
-		_mh(resize)(arg, h);
-	else if (mh_unlikely(h->n_dirty >= h->upper_bound)) {
-		if (_mh(start_resize)(arg, h, h->n_buckets + 1, 0))
-			goto put_done;
-	}
-	if (h->resize_position)
-		_mh(put)(arg, h->shadow, val, NULL);
-#else
-	if (mh_unlikely(h->n_dirty >= h->upper_bound)) {
-		if (_mh(start_resize)(arg, h, h->n_buckets + 1, h->size))
-			goto put_done;
-	}
-#endif
-
-	x = put_slot(arg, h, val);
-	int exist = mh_exist(h, x);
-	if (ret)
-		*ret = !exist;
-
-	if (!exist) {
-		/* add new */
-		mh_setexist(h, x);
-		h->size++;
-		if (!mh_dirty(h, x))
-			h->n_dirty++;
-
-		h->p[x].val = val;
-	} else {
-		/* replace old */
-		h->p[x].val = val;
-	}
-
-put_done:
-	return x;
-}
-
-static inline void
-_mh(del)(mh_arg_t arg, struct _mh(t) *h, mh_int_t x)
-{
-	if (x != h->n_buckets && mh_exist(h, x)) {
-		mh_setfree(h, x);
-		h->size--;
-		if (!mh_dirty(h, x))
-			h->n_dirty--;
-#if MH_INCREMENTAL_RESIZE
-		if (mh_unlikely(h->resize_position))
-			_mh(del_resize)(arg, h, x);
-#endif
-	}
-}
-#endif
-
-
-#ifdef MH_SOURCE
-
-void __attribute__((noinline))
-_mh(del_resize)(mh_arg_t arg, struct _mh(t) *h, mh_int_t x)
-{
-	struct _mh(t) *s = h->shadow;
-	uint32_t y = _mh(get)(arg, s, h->p[x].val);
-	_mh(del)(arg, s, y);
-	_mh(resize)(arg, h);
-}
-
-void
-_mh(init)(struct _mh(t) *h)
-{
-	memset(h, 0, sizeof(struct _mh(t)));
-	h->shadow = calloc(1, sizeof(*h));
-	h->prime = 0;
-	h->n_buckets = __ac_prime_list[h->prime];
-	h->p = calloc(h->n_buckets, sizeof(struct _mh(pair)));
-	h->b = calloc(h->n_buckets / 16 + 1, sizeof(unsigned));
-	h->upper_bound = h->n_buckets * MH_DENSITY;
-}
-
-void
-_mh(clear)(struct _mh(t) *h)
-{
-	free(h->p);
-	h->prime = 0;
-	h->n_buckets = __ac_prime_list[h->prime];
-	h->p = calloc(h->n_buckets, sizeof(struct _mh(pair)));
-	h->upper_bound = h->n_buckets * MH_DENSITY;
-}
-
-void
-_mh(destroy)(struct _mh(t) *h)
-{
-	free(h->shadow);
-	free(h->b);
-	free(h->p);
-}
-
-void
-_mh(resize)(mh_arg_t arg, struct _mh(t) *h)
-{
-	struct _mh(t) *s = h->shadow;
-#if MH_INCREMENTAL_RESIZE
-	mh_int_t  batch = h->batch;
-#endif
-	for (mh_int_t i = h->resize_position; i < h->n_buckets; i++) {
-#if MH_INCREMENTAL_RESIZE
-		if (batch-- == 0) {
-			h->resize_position = i;
-			return;
-		}
-#endif
-		if (!mh_exist(h, i))
-			continue;
-		mh_int_t n = put_slot(arg, s, h->p[i].val);
-		s->p[n] = h->p[i];
-		mh_setexist(s, n);
-		s->n_dirty++;
-	}
-	free(h->p);
-	free(h->b);
-	s->size = h->size;
-	memcpy(h, s, sizeof(*h));
-	h->resize_cnt++;
-}
-
-int
-_mh(start_resize)(mh_arg_t arg, struct _mh(t) *h, mh_int_t buckets, mh_int_t batch)
-{
-	if (h->resize_position) {
-		/* resize has already been started */
-		return 0;
-	}
-	if (buckets < h->n_buckets) {
-		/* hash size is already greater than requested */
-		return 0;
-	}
-	while (h->prime < __ac_HASH_PRIME_SIZE) {
-		if (__ac_prime_list[h->prime] >= buckets)
-			break;
-		h->prime += 1;
-	}
-
-	h->batch = batch > 0 ? batch : h->n_buckets / (256 * 1024);
-	if (h->batch < 256) {
-		/*
-		 * Minimal batch must be greater or equal to
-		 * 1 / (1 - f), where f is upper bound percent
-		 * = MH_DENSITY
-		 */
-		h->batch = 256;
-	}
-
-	struct _mh(t) *s = h->shadow;
-	memcpy(s, h, sizeof(*h));
-	s->resize_position = 0;
-	s->n_buckets = __ac_prime_list[h->prime];
-	s->upper_bound = s->n_buckets * MH_DENSITY;
-	s->n_dirty = 0;
-	s->p = malloc(s->n_buckets * sizeof(struct _mh(pair)));
-	if (s->p == NULL)
-		return -1;
-	s->b = calloc(s->n_buckets / 16 + 1, sizeof(unsigned));
-	if (s->b == NULL) {
-		free(s->p);
-		s->p = NULL;
-		return -1;
-	}
-	_mh(resize)(arg, h);
-
-	return 0;
-}
-
-void
-_mh(reserve)(mh_arg_t arg, struct _mh(t) *h, mh_int_t size)
-{
-	_mh(start_resize)(arg, h, size/MH_DENSITY, h->size);
-}
-
-#ifndef mh_stat
-#define mh_stat(buf, h) ({						\
-                tbuf_printf(buf, "  n_buckets: %"PRIu32 CRLF		\
-			    "  n_dirty: %"PRIu32 CRLF			\
-			    "  size: %"PRIu32 CRLF			\
-			    "  resize_cnt: %"PRIu32 CRLF		\
-			    "  resize_position: %"PRIu32 CRLF,		\
-			    h->n_buckets,				\
-			    h->n_dirty,					\
-			    h->size,					\
-			    h->resize_cnt,				\
-			    h->resize_position);			\
-			})
-#endif
-
-#ifdef MH_DEBUG
-void
-_mh(dump)(struct _mh(t) *h)
-{
-	printf("slots:\n");
-	int k = 0;
-	for(int i = 0; i < h->n_buckets; i++) {
-		if (mh_dirty(h, i) || mh_exist(h, i)) {
-			printf("   [%i] ", i);
-			if (mh_exist(h, i)) {
-				printf("   -> %i", (int)h->p[i].key);
-				k++;
-			}
-			if (mh_dirty(h, i))
-				printf(" dirty");
-			printf("\n");
-		}
-	}
-	printf("end(%i)\n", k);
-}
-#endif
-
-#endif
-
-#if defined(MH_SOURCE) || defined(MH_UNDEF)
-#undef MH_HEADER
-#undef mh_key_t
-#undef mh_val_t
-#undef mh_name
-#undef mh_hash
-#undef mh_eq
-#undef mh_dirty
-#undef mh_place
-#undef mh_setdirty
-#undef mh_setexist
-#undef mh_setvalue
-#undef mh_unlikely
-#undef slot
-#undef slot_and_dirty
-#undef MH_DENSITY
-#endif
-
-#undef mh_cat
-#undef mh_ecat
-#undef _mh
diff --git a/client/tarantool_checksum/tc_file.c b/client/tarantool_checksum/tc_file.c
index 458b2bb24b..3e69249628 100644
--- a/client/tarantool_checksum/tc_file.c
+++ b/client/tarantool_checksum/tc_file.c
@@ -71,26 +71,26 @@ int tc_file_save_space(struct tc_space *s, FILE *f)
 {
 	struct tc_file_header_space h = {
 		.space = s->id,
-		.count_log = s->hash_log.size,
-		.count_snap = s->hash_snap.size,
+		.count_log = s->hash_log->size,
+		.count_snap = s->hash_snap->size,
 		.data_offset = 0
 	};
 
 	fwrite(&h, sizeof(struct tc_file_header_space), 1, f);
 
 	mh_int_t pos = 0;
-	while (pos != mh_end(&s->hash_log)) {
-		if (mh_exist((&s->hash_log), pos)) {
-			struct tc_key *k = mh_value(&s->hash_log, pos);
+	while (pos != mh_end(s->hash_log)) {
+		if (mh_exist((s->hash_log), pos)) {
+			const struct tc_key *k = *mh_pk_node(s->hash_log, pos);
 			if (fwrite((char*)k, sizeof(struct tc_key) + k->size, 1, f) != 1)
 				return -1;
 		}
 		pos++;
 	}
 	pos = 0;
-	while (pos != mh_end(&s->hash_snap)) {
-		if (mh_exist((&s->hash_snap), pos)) {
-			struct tc_key *k = mh_value(&s->hash_snap, pos);
+	while (pos != mh_end(s->hash_snap)) {
+		if (mh_exist((s->hash_snap), pos)) {
+			const struct tc_key *k = *mh_pk_node(s->hash_snap, pos);
 			if (fwrite((char*)k, sizeof(struct tc_key) + k->size, 1, f) != 1)
 				return -1;
 		}
@@ -124,7 +124,7 @@ int tc_file_save(struct tc_spaces *s,
 	mh_int_t pos = 0;
 	while (pos != mh_end(s->t)) {
 		if (mh_exist((s->t), pos)) {
-			struct tc_space *space = mh_value(s->t, pos);
+			struct tc_space *space = mh_u32ptr_node(s->t, pos)->val;
 			int rc = tc_file_save_space(space, f);
 			if (rc == -1) {
 				fclose(f);
@@ -192,8 +192,10 @@ int tc_file_load(struct tc_spaces *s, char *file,
 				fclose(f);
 				return -1;
 			}
-			mh_int_t pos = mh_pk_put(space, &space->hash_log, k, NULL);
-			if (pos == mh_end(&space->hash_log)) {
+			const struct tc_key *node = k;
+			mh_int_t pos = mh_pk_put(space->hash_log, &node,
+						  space, space, NULL);
+			if (pos == mh_end(space->hash_log)) {
 				fclose(f);
 				return -1;
 			}
@@ -207,8 +209,10 @@ int tc_file_load(struct tc_spaces *s, char *file,
 				fclose(f);
 				return -1;
 			}
-			mh_int_t pos = mh_pk_put(space, &space->hash_snap, k, NULL);
-			if (pos == mh_end(&space->hash_log)) {
+			const struct tc_key *node = k;
+			mh_int_t pos = mh_pk_put(space->hash_snap, &node,
+						 space, space, NULL);
+			if (pos == mh_end(space->hash_log)) {
 				fclose(f);
 				return -1;
 			}
diff --git a/client/tarantool_checksum/tc_generate.c b/client/tarantool_checksum/tc_generate.c
index 35a64c1c77..3ee329393b 100644
--- a/client/tarantool_checksum/tc_generate.c
+++ b/client/tarantool_checksum/tc_generate.c
@@ -55,9 +55,8 @@
 #include "tc_file.h"
 
 uint32_t
-search_hash(void *x, const struct tc_key *k)
+search_hash(const struct tc_key *k, struct tc_space *s)
 {
-	struct tc_space *s = x;
 	uint32_t h = 13;
 	int i;
 	for (i = 0; i < s->pk.count; i++) {
@@ -87,12 +86,12 @@ search_hash(void *x, const struct tc_key *k)
 }
 
 int
-search_equal(void *x, const struct tc_key *a,
-	     const struct tc_key *b)
+search_equal(const struct tc_key *a,
+	     const struct tc_key *b, struct tc_space *s)
 {
 	if (a->size != b->size)
 		return 0;
-	struct tc_space *s = x;
+
 	int i;
 	for (i = 0; i < s->pk.count; i++) {
 		switch (s->pk.fields[i].type) {
@@ -226,8 +225,9 @@ tc_generate_entry(struct tc_spaces *s, struct tnt_request *r)
 		return -1;
 	}
 	/* 3. put into hash */
-	mh_int_t pos = mh_pk_put(space, &space->hash_log, k, NULL);
-	if (pos == mh_end(&space->hash_log)) {
+	const struct tc_key *node = k;
+	mh_int_t pos = mh_pk_put(space->hash_log, &node, space, space, NULL);
+	if (pos == mh_end(space->hash_log)) {
 		free(k);
 		return -1;
 	}
@@ -372,14 +372,17 @@ tc_generate_snaprow(struct tc_spaces *s, struct tnt_iter_storage *is,
 
 	/* foreach snapshot row which does not exist in index dump:
 	 * calculate crc and add to the index */
-	mh_int_t pos = mh_pk_get(space, &space->hash_log, k);
-	struct tc_key *v = NULL;
-	if (pos != mh_end(&space->hash_log))
-		v = mh_value(&space->hash_log, pos);
+	const struct tc_key *node = k;
+	mh_int_t pos = mh_pk_get(space->hash_log, &node, space, space);
+	const struct tc_key *v = NULL;
+	if (pos != mh_end(space->hash_log))
+		v = *mh_pk_node(space->hash_log, pos);
 	if (v == NULL) {
 		k->crc = crc32c(0, (unsigned char*)is->t.data, is->t.size);
-		mh_int_t pos = mh_pk_put(space, &space->hash_snap, k, NULL);
-		if (pos == mh_end(&space->hash_snap)) {
+		const struct tc_key *node = k;
+		mh_int_t pos = mh_pk_put(space->hash_snap, &node,
+					 space, space, NULL);
+		if (pos == mh_end(space->hash_snap)) {
 			free(k);
 			return -1;
 		}
diff --git a/client/tarantool_checksum/tc_hash.h b/client/tarantool_checksum/tc_hash.h
index 2da7d339ae..3f8694a56d 100644
--- a/client/tarantool_checksum/tc_hash.h
+++ b/client/tarantool_checksum/tc_hash.h
@@ -5,25 +5,37 @@
 #define MH_UNDEF
 #endif
 
-typedef void* ptr_t;
+#include <stdint.h>
 
 #define mh_name _u32ptr
-#define mh_key_t uint32_t
-#define mh_val_t ptr_t
-#define mh_hash(a) (a)
-#define mh_eq(a, b) ((a) == (b))
+struct mh_u32ptr_node_t {
+	uint32_t key;
+	void *val;
+};
+
+#define mh_node_t struct mh_u32ptr_node_t
+#define mh_hash_arg_t void *
+#define mh_hash(a, arg) (a->key)
+#define mh_eq_arg_t void *
+#define mh_eq(a, b, arg) ((a->key) == (b->key))
 #include <mhash.h>
 
-uint32_t search_hash(void *x, const struct tc_key *k);
-int search_equal(void *x, const struct tc_key *a, const struct tc_key *b);
 
-#undef put_slot
+struct tc_space;
+
+uint32_t
+search_hash(const struct tc_key *k, struct tc_space *s);
+
+int
+search_equal(const struct tc_key *a, const struct tc_key *b,
+	     struct tc_space *s);
 
 #define mh_name _pk
-#define mh_arg_t void*
-#define mh_val_t struct tc_key*
-#define mh_hash(x, k) search_hash((x), (k))
-#define mh_eq(x, ka, kb) search_equal((x), (ka), (kb))
-#include "mhash-val.h"
+#define mh_node_t struct tc_key *
+#define mh_hash_arg_t struct tc_space *
+#define mh_hash(a, arg) search_hash(*(a), arg)
+#define mh_eq_arg_t struct tc_space *
+#define mh_eq(a, b, arg) search_equal(*(a), *(b), arg)
+#include <mhash.h>
 
 #endif
diff --git a/client/tarantool_checksum/tc_space.c b/client/tarantool_checksum/tc_space.c
index fdd0301090..cf015c29d8 100644
--- a/client/tarantool_checksum/tc_space.c
+++ b/client/tarantool_checksum/tc_space.c
@@ -53,28 +53,30 @@ void tc_space_free(struct tc_spaces *s)
 {
 	mh_int_t i;
 	mh_foreach(s->t, i) {
-		struct tc_space *space = mh_value(s->t, i);
-		mh_u32ptr_del(s->t, i);
+		struct tc_space *space = mh_u32ptr_node(s->t, i)->val;
+		mh_u32ptr_del(s->t, i, NULL, NULL);
 
 		mh_int_t pos = 0;
-		while (pos != mh_end(&space->hash_log)) {
-			if (mh_exist((&space->hash_log), pos)) {
-				struct tc_key *k = mh_value(&space->hash_log, pos);
+		while (pos != mh_end(space->hash_log)) {
+			if (mh_exist((space->hash_log), pos)) {
+				struct tc_key *k = (struct tc_key *)
+					*mh_pk_node(space->hash_log, pos);
 				free(k);
 			}
 			pos++;
 		}
 		pos = 0;
-		while (pos != mh_end(&space->hash_snap)) {
-			if (mh_exist((&space->hash_snap), pos)) {
-				struct tc_key *k = mh_value(&space->hash_snap, pos);
+		while (pos != mh_end(space->hash_snap)) {
+			if (mh_exist((space->hash_snap), pos)) {
+				struct tc_key *k = (struct tc_key *)
+					*mh_pk_node(space->hash_snap, pos);
 				free(k);
 			}
 			pos++;
 		}
 
-		mh_pk_destroy(&space->hash_log);
-		mh_pk_destroy(&space->hash_snap);
+		mh_pk_destroy(space->hash_log);
+		mh_pk_destroy(space->hash_snap);
 
 		free(space->pk.fields);
 		free(space);
@@ -88,18 +90,21 @@ struct tc_space *tc_space_create(struct tc_spaces *s, uint32_t id) {
 		return NULL;
 	memset(space, 0, sizeof(struct tc_space));
 	space->id = id;
-	mh_pk_init(&space->hash_log);
-	mh_pk_init(&space->hash_snap);
+	space->hash_log = mh_pk_init();
+	space->hash_snap = mh_pk_init();
 	int ret;
-	mh_u32ptr_put(s->t, space->id, space, &ret);
+
+	const struct mh_u32ptr_node_t node = { .key = space->id, .val = space };
+	mh_u32ptr_put(s->t, &node, space, space, &ret);
 	return space;
 }
 
 struct tc_space *tc_space_match(struct tc_spaces *s, uint32_t id) {
-	mh_int_t k = mh_u32ptr_get(s->t, id);
+	const struct mh_u32ptr_node_t node = { .key = id };
+	mh_int_t k = mh_u32ptr_get(s->t, &node, NULL, NULL);
 	struct tc_space *space = NULL;
 	if (k != mh_end(s->t))
-		space = mh_value(s->t, k);
+		space = mh_u32ptr_node(s->t, k)->val;
 	return space;
 }
 
diff --git a/client/tarantool_checksum/tc_space.h b/client/tarantool_checksum/tc_space.h
index 4febba66ee..7c08701e04 100644
--- a/client/tarantool_checksum/tc_space.h
+++ b/client/tarantool_checksum/tc_space.h
@@ -20,8 +20,8 @@ struct tc_space_key {
 
 struct tc_space {
 	uint32_t id;
-	struct mh_pk_t hash_log;
-	struct mh_pk_t hash_snap;
+	struct mh_pk_t *hash_log;
+	struct mh_pk_t *hash_snap;
 	struct tc_space_key pk;
 };
 
diff --git a/client/tarantool_checksum/tc_verify.c b/client/tarantool_checksum/tc_verify.c
index 2ed840c67e..18321a55a6 100644
--- a/client/tarantool_checksum/tc_verify.c
+++ b/client/tarantool_checksum/tc_verify.c
@@ -74,20 +74,22 @@ int tc_verify_cmp(struct tc_spaces *s,
 	}
 
 	/* 1. check in hash, if found then skip */
-	mh_int_t pos = mh_pk_get(space, &space->hash_log, k);
-	struct tc_key *v = NULL;
-	if (pos != mh_end(&space->hash_log))
-		v = mh_value(&space->hash_log, pos);
+	const struct tc_key *node = k;
+	mh_int_t pos = mh_pk_get(space->hash_log, &node, space, space);
+	const struct tc_key *v = NULL;
+	if (pos != mh_end(space->hash_log))
+		v = *mh_pk_node(space->hash_log, pos);
 	if (v) {
 		rc = 0;
 		goto done;
 	}
 
 	/* 2. if key was not found in xlog hash, then try snapshot hash */
-	pos = mh_pk_get(space, &space->hash_snap, k);
+	node = k;
+	pos = mh_pk_get(space->hash_snap, &node, space, space);
 	v = NULL;
-	if (pos != mh_end(&space->hash_snap))
-		v = mh_value(&space->hash_snap, pos);
+	if (pos != mh_end(space->hash_snap))
+		v = *mh_pk_node(space->hash_snap, pos);
 	if (v) {
 		/* generate and compare checksum */
 		uint32_t crc = crc32c(0, (unsigned char*)is->t.data, is->t.size);
diff --git a/client/tarantool_checksum/tnt_checksum.cbp b/client/tarantool_checksum/tnt_checksum.cbp
new file mode 100644
index 0000000000..bee452f1b7
--- /dev/null
+++ b/client/tarantool_checksum/tnt_checksum.cbp
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+   <FileVersion major="1" minor="6" />
+   <Project>
+      <Option title="tnt_checksum" />
+      <Option makefile_is_custom="1" />
+      <Option compiler="gcc" />
+      <Option virtualFolders="CMake Files\;CMake Files\cmake\;CMake Files\include\;CMake Files\doc\;CMake Files\doc\www-data.in\;CMake Files\doc\man\;CMake Files\third_party\;CMake Files\third_party\coro\;CMake Files\third_party\gopt\;CMake Files\cfg\;CMake Files\connector\;CMake Files\connector\c\;CMake Files\connector\c\tnt\;CMake Files\connector\c\tntsql\;CMake Files\connector\c\tntnet\;CMake Files\connector\c\tntrpl\;CMake Files\connector\c\include\;CMake Files\src\;CMake Files\src\box\;CMake Files\extra\;CMake Files\client\;CMake Files\client\tarantool_checksum\;CMake Files\test\;CMake Files\test\unit\;CMake Files\test\box\;CMake Files\test\connector_c\;" />
+      <Build>
+      <Target title="all">
+         <Option working_dir="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum" />
+         <Option type="4" />
+         <MakeCommands>
+            <Build command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 all" />
+            <CompileFile command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 &quot;$file&quot;" />
+            <Clean command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 clean" />
+            <DistClean command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 clean" />
+         </MakeCommands>
+      </Target>
+      <Target title="tarantool_checksum">
+         <Option output="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tarantool_checksum" prefix_auto="0" extension_auto="0" />
+         <Option working_dir="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum" />
+         <Option object_output="./" />
+         <Option type="1" />
+         <Option compiler="gcc" />
+         <Compiler>
+            <Add directory="/data/work/tarantool-hashtable-refactoring" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/connector/c/include" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/include" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/third_party/libobjc" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/third_party/luajit/src" />
+            <Add directory="/usr/include" />
+            <Add directory="/usr/include/c++/4.7" />
+            <Add directory="/usr/include/c++/4.7/backward" />
+            <Add directory="/usr/include/c++/4.7/x86_64-linux-gnu" />
+            <Add directory="/usr/include/x86_64-linux-gnu" />
+            <Add directory="/usr/lib/gcc/x86_64-linux-gnu/4.7/include" />
+            <Add directory="/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed" />
+            <Add directory="/usr/local/include" />
+         </Compiler>
+         <MakeCommands>
+            <Build command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 tarantool_checksum" />
+            <CompileFile command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 &quot;$file&quot;" />
+            <Clean command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 clean" />
+            <DistClean command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 clean" />
+         </MakeCommands>
+      </Target>
+      <Target title="tarantool_checksum/fast">
+         <Option output="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tarantool_checksum" prefix_auto="0" extension_auto="0" />
+         <Option working_dir="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum" />
+         <Option object_output="./" />
+         <Option type="1" />
+         <Option compiler="gcc" />
+         <Compiler>
+            <Add directory="/data/work/tarantool-hashtable-refactoring" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/connector/c/include" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/include" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/third_party/libobjc" />
+            <Add directory="/data/work/tarantool-hashtable-refactoring/third_party/luajit/src" />
+            <Add directory="/usr/include" />
+            <Add directory="/usr/include/c++/4.7" />
+            <Add directory="/usr/include/c++/4.7/backward" />
+            <Add directory="/usr/include/c++/4.7/x86_64-linux-gnu" />
+            <Add directory="/usr/include/x86_64-linux-gnu" />
+            <Add directory="/usr/lib/gcc/x86_64-linux-gnu/4.7/include" />
+            <Add directory="/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed" />
+            <Add directory="/usr/local/include" />
+         </Compiler>
+         <MakeCommands>
+            <Build command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 tarantool_checksum/fast" />
+            <CompileFile command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 &quot;$file&quot;" />
+            <Clean command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 clean" />
+            <DistClean command="/usr/bin/make -f &quot;/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/Makefile&quot;  VERBOSE=1 clean" />
+         </MakeCommands>
+      </Target>
+      </Build>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_config.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_file.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_generate.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_main.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_options.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_space.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_verify.c">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_config.h">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_file.h">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_generate.h">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_options.h">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_space.h">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/tc_verify.h">
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/arch.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/os.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/compiler.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/check_objective_c_compiler.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/libobjc.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/luajit.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cmake/cpack.cmake">
+          <Option virtualFolder="CMake Files\cmake\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/include/config.h.cmake">
+          <Option virtualFolder="CMake Files\include\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/doc/tnt.ent.cmake">
+          <Option virtualFolder="CMake Files\doc\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/doc/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\doc\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/doc/www-data.in/download.cmake">
+          <Option virtualFolder="CMake Files\doc\www-data.in\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/doc/www-data.in/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\doc\www-data.in\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/doc/man/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\doc\man\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/third_party/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\third_party\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/third_party/coro/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\third_party\coro\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/third_party/gopt/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\third_party\gopt\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/cfg/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\cfg\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tnt/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tnt\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tnt/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tnt\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tntsql/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tntsql\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tntsql/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tntsql\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tntnet/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tntnet\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tntnet/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tntnet\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tntrpl/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tntrpl\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/tntrpl/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\tntrpl\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/connector/c/include/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\connector\c\include\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/src/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\src\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/src/box/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\src\box\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/extra/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\extra\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\client\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\client\tarantool_checksum\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/client/tarantool_checksum/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\client\tarantool_checksum\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/test/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\test\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/test/unit/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\test\unit\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/test/box/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\test\box\" />
+      </Unit>
+      <Unit filename="/data/work/tarantool-hashtable-refactoring/test/connector_c/CMakeLists.txt">
+          <Option virtualFolder="CMake Files\test\connector_c\" />
+      </Unit>
+   </Project>
+</CodeBlocks_project_file>
-- 
GitLab