Skip to content
Snippets Groups Projects
Commit 4974b057 authored by Roman Tsisyk's avatar Roman Tsisyk
Browse files

BitsetIndex implementation (initial import)

parent 8d700c37
No related branches found
No related tags found
No related merge requests found
...@@ -26,4 +26,7 @@ add_custom_target(generate_lua_sources} ...@@ -26,4 +26,7 @@ add_custom_target(generate_lua_sources}
set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${lua_sources}) set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${lua_sources})
tarantool_module("box" tuple.m index.m hash_index.m tree_index.m space.m tarantool_module("box" tuple.m index.m hash_index.m tree_index.m space.m
port.m request.m txn.m box.m ${lua_sources} box_lua.m box_lua_space.m) port.m request.m txn.m box.m ${lua_sources} box_lua.m box_lua_space.m
bitset_index.m)
target_link_libraries(tarantool_box bitset)
#ifndef TARANTOOL_BOX_INDEX_BITSET_H_INCLUDED
#define TARANTOOL_BOX_INDEX_BITSET_H_INCLUDED
/*
* 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.
*/
/**
* @brief Objective C wrapper for bitset_index
* @see bitset/index.h
*/
#include "index.h"
#include <lib/bitset/index.h>
struct bitset_index;
struct bitset_expr;
@interface BitsetIndex: Index {
@private
struct bitset_index index;
}
@end
#endif /* TARANTOOL_BOX_INDEX_BITSET_H_INCLUDED */
/*
* 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.
*/
#include "bitset_index.h"
#include <string.h>
#include "salloc.h"
#include "tuple.h"
#include "space.h"
#include "exception.h"
#include "pickle.h"
#include <lib/bitset/index.h>
static struct index_traits bitset_index_traits = {
.allows_partial_key = false,
};
static inline size_t
tuple_to_value(struct tuple *tuple)
{
#if 0
size_t value = salloc_ptr_to_index(tuple);
assert(salloc_ptr_from_index(value) == tuple);
return value;
#endif
return (size_t) tuple;
}
static inline struct tuple *
value_to_tuple(size_t value)
{
#if 0
return salloc_ptr_from_index(value);
#endif
return (struct tuple *) value;
}
struct iterator_wrapper {
struct iterator base; /* Must be the first member. */
struct bitset_iterator bitset_it;
};
static struct iterator_wrapper *
iterator_wrapper(struct iterator *it)
{
return (struct iterator_wrapper *) it;
}
void
iterator_wrapper_free(struct iterator *iterator)
{
assert(iterator->free == iterator_wrapper_free);
struct iterator_wrapper *it = iterator_wrapper(iterator);
bitset_iterator_destroy(&it->bitset_it);
free(it);
}
struct tuple *
iterator_wrapper_next(struct iterator *iterator)
{
assert(iterator->free == iterator_wrapper_free);
struct iterator_wrapper *it = iterator_wrapper(iterator);
size_t value = bitset_iterator_next(&it->bitset_it);
if (value == SIZE_MAX)
return NULL;
return value_to_tuple(value);
}
@implementation BitsetIndex;
+ (struct index_traits *) traits
{
return &bitset_index_traits;
}
- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
{
assert (!key_def_arg->is_unique);
self = [super init: key_def_arg :space_arg];
assert (self != NULL);
if (bitset_index_create(&self->index, realloc) != 0)
panic_syserror("bitset_index_create");
return self;
}
- (void) free
{
bitset_index_destroy(&self->index);
[super free];
}
- (void) beginBuild
{
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "beginBuild()");
}
- (void) buildNext: (struct tuple *)tuple
{
(void) tuple;
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "buildNext()");
}
- (void) endBuild
{
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "endBuild()");
}
- (void) build: (Index *) pk
{
assert (!key_def->is_unique);
struct iterator *it = pk->position;
struct tuple *tuple;
[pk initIterator: it :ITER_ALL :NULL :0];
while ((tuple = it->next(it)))
[self replace: NULL :tuple :DUP_INSERT];
}
- (size_t) size
{
return bitset_index_size(&self->index);
}
- (struct tuple *) min
{
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "min()");
return NULL;
}
- (struct tuple *) max
{
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "max()");
return NULL;
}
- (struct iterator *) allocIterator
{
struct iterator_wrapper *it = malloc(sizeof(struct iterator_wrapper));
if (!it)
return NULL;
memset(it, 0, sizeof(struct iterator_wrapper));
it->base.next = iterator_wrapper_next;
it->base.free = iterator_wrapper_free;
bitset_iterator_create(&it->bitset_it, realloc);
return (struct iterator *) it;
}
- (struct tuple *) findByKey: (void *) key :(int) part_count
{
(void) key;
(void) part_count;
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "findByKey()");
return NULL;
}
- (struct tuple *) findByTuple: (struct tuple *) tuple
{
(void) tuple;
tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "findByTuple()");
return NULL;
}
- (struct tuple *) replace: (struct tuple *) old_tuple
: (struct tuple *) new_tuple
: (u32) flags
{
assert(!key_def->is_unique);
assert(old_tuple != NULL || new_tuple != NULL);
(void) flags;
struct tuple *ret = NULL;
if (old_tuple != NULL) {
size_t value = tuple_to_value(old_tuple);
#if defined(DEBUG)
say_debug("BitsetIndex: remove value = %zu (%p)",
value, old_tuple);
#endif /* defined(DEBUG) */
if (bitset_index_contains_value(&self->index, value)) {
ret = old_tuple;
assert (old_tuple != new_tuple);
bitset_index_remove_value(&self->index, value);
}
}
if (new_tuple != NULL) {
const void *field = tuple_field(new_tuple,
key_def->parts[0].fieldno);
assert (field != NULL);
size_t bitset_key_size = (size_t) load_varint32(&field);
const void *bitset_key = field;
size_t value = tuple_to_value(new_tuple);
#if defined(DEBUG)
say_debug("BitsetIndex: insert value = %zu (%p)",
value, new_tuple);
#endif /* defined(DEBUG) */
if (bitset_index_insert(&self->index, bitset_key,
bitset_key_size, value) < 0) {
tnt_raise(ClientError, :ER_MEMORY_ISSUE, 0,
"BitsetIndex", "insert");
}
}
return ret;
}
- (void) initIterator: (struct iterator *) iterator:(enum iterator_type) type
:(const void *) key :(int) part_count
{
assert(iterator->free == iterator_wrapper_free);
struct iterator_wrapper *it = iterator_wrapper(iterator);
const void *bitset_key = NULL;
size_t bitset_key_size = 0;
if (type != ITER_ALL) {
check_key_parts(key_def, part_count,
bitset_index_traits.allows_partial_key);
const void *key2 = key;
bitset_key_size = (size_t) load_varint32(&key2);
bitset_key = key2;
}
struct bitset_expr expr;
bitset_expr_create(&expr, realloc);
@try {
int rc = 0;
switch (type) {
case ITER_ALL:
rc = bitset_index_expr_all(&expr);
break;
case ITER_EQ:
rc = bitset_index_expr_equals(&expr, bitset_key,
bitset_key_size);
break;
case ITER_BITS_ALL_SET:
rc = bitset_index_expr_all_set(&expr, bitset_key,
bitset_key_size);
break;
case ITER_BITS_ALL_NOT_SET:
rc = bitset_index_expr_all_not_set(&expr, bitset_key,
bitset_key_size);
break;
case ITER_BITS_ANY_SET:
rc = bitset_index_expr_any_set(&expr, bitset_key,
bitset_key_size);
break;
default:
tnt_raise(ClientError, :ER_UNSUPPORTED,
"BitsetIndex", "requested iterator type");
}
if (rc != 0) {
tnt_raise(ClientError, :ER_MEMORY_ISSUE,
0, "BitsetIndex", "iterator expression");
}
if (bitset_index_init_iterator(&self->index, &it->bitset_it,
&expr) != 0) {
tnt_raise(ClientError, :ER_MEMORY_ISSUE,
0, "BitsetIndex", "iterator state");
}
} @finally {
bitset_expr_destroy(&expr);
}
}
@end
...@@ -43,9 +43,10 @@ struct space; ...@@ -43,9 +43,10 @@ struct space;
enum field_data_type { UNKNOWN = -1, NUM = 0, NUM64, STRING, field_data_type_MAX }; enum field_data_type { UNKNOWN = -1, NUM = 0, NUM64, STRING, field_data_type_MAX };
extern const char *field_data_type_strs[]; extern const char *field_data_type_strs[];
#define INDEX_TYPE(_) \ #define INDEX_TYPE(_) \
_(HASH, 0) /* HASH Index */ \ _(HASH, 0) /* HASH Index */ \
_(TREE, 1) /* TREE Index */ \ _(TREE, 1) /* TREE Index */ \
_(BITSET, 2) /* BITSET Index */ \
ENUM(index_type, INDEX_TYPE); ENUM(index_type, INDEX_TYPE);
extern const char *index_type_strs[]; extern const char *index_type_strs[];
...@@ -79,6 +80,9 @@ extern const char *index_type_strs[]; ...@@ -79,6 +80,9 @@ extern const char *index_type_strs[];
_(ITER_LE, 4) /* key <= x */ \ _(ITER_LE, 4) /* key <= x */ \
_(ITER_GE, 5) /* key >= x */ \ _(ITER_GE, 5) /* key >= x */ \
_(ITER_GT, 6) /* key > x */ \ _(ITER_GT, 6) /* key > x */ \
_(ITER_BITS_ALL_SET, 7) /* all bits from x are set in key */ \
_(ITER_BITS_ANY_SET, 8) /* at least one x's bit is set */ \
_(ITER_BITS_ALL_NOT_SET, 9) /* all bits are not set */ \
ENUM(iterator_type, ITERATOR_TYPE); ENUM(iterator_type, ITERATOR_TYPE);
extern const char *iterator_type_strs[]; extern const char *iterator_type_strs[];
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "index.h" #include "index.h"
#include "hash_index.h" #include "hash_index.h"
#include "tree_index.h" #include "tree_index.h"
#include "bitset_index.h"
#include "tuple.h" #include "tuple.h"
#include "say.h" #include "say.h"
#include "exception.h" #include "exception.h"
...@@ -108,6 +109,8 @@ replace_check_dup(struct tuple *old_tuple, ...@@ -108,6 +109,8 @@ replace_check_dup(struct tuple *old_tuple,
return [HashIndex alloc: key_def :space]; return [HashIndex alloc: key_def :space];
case TREE: case TREE:
return [TreeIndex alloc: key_def :space]; return [TreeIndex alloc: key_def :space];
case BITSET:
return [BitsetIndex alloc];
default: default:
assert(false); assert(false);
} }
......
...@@ -572,6 +572,21 @@ check_spaces(struct tarantool_cfg *conf) ...@@ -572,6 +572,21 @@ check_spaces(struct tarantool_cfg *conf)
case TREE: case TREE:
/* extra check for tree index not needed */ /* extra check for tree index not needed */
break; break;
case BITSET:
/* check bitset index */
/* bitset index must has single-field key */
if (key_part_count != 1) {
out_warning(0, "(space = %zu index = %zu) "
"bitset index must has a single-field key", i, j);
return -1;
}
/* bitset index must not be unique */
if (index->unique) {
out_warning(0, "(space = %zu index = %zu) "
"bitset index must be non-unique", i, j);
return -1;
}
break;
default: default:
assert(false); assert(false);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment