Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org, imeevma@tarantool.org
Subject: [tarantool-patches] Re: [PATCH 4/5] Primary index for ephemeral spaces
Date: Fri, 13 Jul 2018 19:32:20 +0300	[thread overview]
Message-ID: <e0ea34bf-82b8-e703-ef53-c5fc7f6a173f@tarantool.org> (raw)
In-Reply-To: <64b848161d6b598dba2b0ae40d89c4d4c744682f.1531393821.git.imeevma@gmail.com>

Thanks for the patch! See 18 comments below.

On 12/07/2018 14:16, imeevma@tarantool.org wrote:
> Functions for creation and deletion primary index
> of ephemeral space added.
> 
> Part of #3375.
> ---
>   src/box/index_def.c               |  42 +++++++
>   src/box/index_def.h               |  18 +++
>   src/box/lua/schema.lua            | 130 ++++++++++++++++++++++
>   src/box/lua/space.cc              |  92 ++++++++++++++++
>   test/box/ephemeral_space.result   | 225 ++++++++++++++++++++++++++++++++++++--
>   test/box/ephemeral_space.test.lua |  88 +++++++++++++--
>   test/engine/iterator.result       |   2 +-
>   7 files changed, 582 insertions(+), 15 deletions(-)
> 
> diff --git a/src/box/index_def.c b/src/box/index_def.c
> index e0d54c0..9622dce 100644
> --- a/src/box/index_def.c
> +++ b/src/box/index_def.c
> @@ -31,6 +31,8 @@
>   #include "index_def.h"
>   #include "schema_def.h"
>   #include "identifier.h"
> +#include "fiber.h"
> +#include "space.h"

1. Please, do not make index_def depend on space.
Instead of passing struct space to ephemeral_index_def use
directly field_def * array and field_count parameters.

2. Can you find a way how to do not duplicate this code
from alter.cc index_def_new_from_tuple?

>   
>   const char *index_type_strs[] = { "HASH", "TREE", "BITSET", "RTREE" };
>   
> @@ -369,3 +371,43 @@ index_opts_decode(struct index_opts *opts, const char *map,
>   	}
>   	return 0;
>   }
> +
> +struct index_def *
> +ephemeral_index_def(struct space *space, uint32_t index_id,

3. Respect the code style:

_new, _delete names for allocating, initialization and deletion.

> +		    const char *name, const char *type_field,
> +		    const char *opts_field, const char *parts)
> +{
> +	const struct field_def *fields = space->def->fields;
> +	uint32_t field_count = space->def->field_count;
> +	struct index_opts opts;
> +	struct key_def *key_def = NULL;
> +	uint32_t part_count = mp_decode_array(&parts);
> +	enum index_type type = STR2ENUM(index_type, type_field);
> +	if(index_opts_decode(&opts, opts_field, &fiber()->gc) != 0)

4. + white space after 'if'. I will not mention it anymore, but please,
find other places yourself.

> +		return NULL;
> +	if(identifier_check(name, strlen(name)) != 0)
> +		return NULL;
> +	struct key_part_def *part_def = (struct key_part_def *)
> +			malloc(sizeof(*part_def) * part_count);

5. Wrong alignment. Rather this:

	struct key_part_def *part_def =
		(struct key_part_def *) malloc(sizeof(*part_def) * part_count);

6. You can use region here and do not free it now, but later using
region_truncate. It reduces count of malloc-free oscillation.

> +	if (part_def == NULL) {
> +		diag_set(OutOfMemory, sizeof(*part_def) * part_count,
> +			 "malloc", "key_part_def");
> +		return NULL;
> +	}
> +	if (key_def_decode_parts(part_def, part_count, &parts,
> +				 fields, field_count) != 0) {
> +		free(part_def);
> +		return NULL;
> +	}
> +	key_def = key_def_new_with_parts(part_def, part_count);
> +	free(part_def);
> +	if (key_def == NULL)
> +		return NULL;
> +	struct index_def *index_def =
> +		index_def_new(0, index_id, name, strlen(name),
> +			      type, &opts, key_def, NULL);
> +	key_def_delete(key_def);
> +	if (index_def == NULL)
> +		return NULL;
> +	return index_def;

7. These 3 lines can be replaced with one 'return index_def'.

> +}
> diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
> index 81f0fa0..0fe109a 100644
> --- a/src/box/lua/schema.lua
> +++ b/src/box/lua/schema.lua
> @@ -527,6 +527,9 @@ box.schema.space.drop_ephemeral = function(ephemeral_space)
>           return
>       end
>       check_param(ephemeral_space.space, 'space', 'cdata')
> +    if ephemeral_space.index ~= nil and ephemeral_space.index[0] ~= nil then

8. How ephemeral_space.index can be nil after the check above (about
ephemeral_space.space == nil)?

> +        ephemeral_space.index[0]:drop()
> +    end
>       space_delete_ephemeral(ephemeral_space)
>       for k,_ in pairs(ephemeral_space) do
>           ephemeral_space[k] = nil
> @@ -1084,6 +1087,128 @@ ffi.metatype(iterator_t, {
>       end;
>   })
>   
> +local index_new_ephemeral = box.internal.space.index_new_ephemeral
> +box.internal.space.index_new_ephemeral = nil
> +local index_delete_ephemeral = box.internal.space.index_delete_ephemeral
> +box.internal.space.index_delete_ephemeral = nil
> +local index_ephemeral_methods = box.schema.index_ephemeral_methods
> +box.schema.index_ephemeral_mt = nil
> +local index_ephemeral_mt = {}
> +
> +local index_ephemeral_create = function(ephemeral_space, name, options)

9. Lets do the same API as for non-ephemeral spaces:
create_index, not index_create.

> +    if type(ephemeral_space) ~= 'table' then
> +        error("Usage: ephemeral_space:create_index(name, opts)")
> +    end
> +    check_param(name, 'name', 'string')
> +    check_param_table(options, create_index_template)
> +    local space = ephemeral_space
> +    local format = space:format()
> +
> +    local options_defaults = {
> +        type = 'tree',
> +    }
> +    options = update_param_table(options, options_defaults)
> +    local type_dependent_defaults = {
> +        rtree = {parts = { 2, 'array' }, unique = false},
> +        bitset = {parts = { 2, 'unsigned' }, unique = false},
> +        other = {parts = { 1, 'unsigned' }, unique = true},
> +    }
> +    options_defaults = type_dependent_defaults[options.type]
> +            or type_dependent_defaults.other
> +    if not options.parts then
> +        local fieldno = options_defaults.parts[1]
> +        if #format >= fieldno then
> +            local t = format[fieldno].type
> +            if t ~= 'any' then
> +                options.parts = {{fieldno, format[fieldno].type}}
> +            end
> +        end
> +    end
> +    options = update_param_table(options, options_defaults)
> +    if space.engine == 'vinyl' then> +        options_defaults = {
> +            page_size = box.cfg.vinyl_page_size,
> +            range_size = box.cfg.vinyl_range_size,
> +            run_count_per_level = box.cfg.vinyl_run_count_per_level,
> +            run_size_ratio = box.cfg.vinyl_run_size_ratio,
> +            bloom_fpr = box.cfg.vinyl_bloom_fpr
> +        }
> +    else
> +        options_defaults = {}
> +    end
> +    options = update_param_table(options, options_defaults)
> +
> +    if ephemeral_space.index ~= nil and ephemeral_space.index[0] then
> +        if options.if_not_exists then
> +            return space.index[0], "not created"
> +        else
> +            error("Primary index for this ephemeral index already exists")
> +        end
> +    end
> +    local iid = 0
> +    if options.id and options.id ~= 0 then
> +        error("Ephemeral space can have only primary index.")
> +    end
> +    local parts, parts_can_be_simplified =
> +        update_index_parts(format, options.parts)
> +    -- create_index() options contains type, parts, etc,
> +    -- stored separately. Remove these members from index_opts
> +    local index_opts = {
> +            dimension = options.dimension,
> +            unique = options.unique,
> +            distance = options.distance,
> +            page_size = options.page_size,
> +            range_size = options.range_size,
> +            run_count_per_level = options.run_count_per_level,
> +            run_size_ratio = options.run_size_ratio,
> +            bloom_fpr = options.bloom_fpr,
> +    }
> +    local field_type_aliases = {
> +        num = 'unsigned'; -- Deprecated since 1.7.2
> +        uint = 'unsigned';
> +        str = 'string';
> +        int = 'integer';
> +        ['*'] = 'any';
> +    };
> +    for _, part in pairs(parts) do
> +        local field_type = part.type:lower()
> +        part.type = field_type_aliases[field_type] or field_type
> +        if field_type == 'num' then
> +            log.warn("field type '%s' is deprecated since Tarantool 1.7, "..
> +                     "please use '%s' instead", field_type, part.type)
> +        end
> +    end
> +    if parts_can_be_simplified then
> +        parts = simplify_index_parts(parts)
> +    end

10. This function again is almost complete duplicate of schema.index.create.
Please, remove code duplication.

> +    space.space = index_new_ephemeral(space, iid, name, options.type,
> +                                      msgpack.encode(index_opts),
> +                                      msgpack.encode(parts))
> +    space.index[iid] = {}
> +    space.index[iid].unique = index_opts.unique or true
> +    space.index[iid].parts = parts
> +    space.index[iid].id = iid
> +    space.index[iid].name = name
> +    space.index[iid].type = type
> +    space.index[iid].options = options
> +    space.index[iid].space = space.space
> +    space.index[iid].ephemeral_space = space
> +    space.index[name] = space.index[iid]
> +    setmetatable(space.index[iid], index_ephemeral_mt)
> +    return space.index[name]
> +end
> +
> +local index_ephemeral_drop = function(ephemeral_index)
> +    if type(ephemeral_index) ~= 'table' then
> +        error("Usage: ephemeral_space.index[0]:drop()")
> +    end
> +    ephemeral_index.ephemeral_space.space = index_delete_ephemeral(ephemeral_index)
> +    ephemeral_index.ephemeral_space.index = {}
> +    for k,_ in pairs(ephemeral_index) do
> +        ephemeral_index[k] = nil
> +    end

11. It will not work, when we will allow multiple indexes. You should not
delete and nullify all indexes when a one is deleted.

> +end
> +
>   local iterator_gen = function(param, state)
>       --[[
>           index:pairs() mostly conforms to the Lua for-in loop conventions and
> diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc
> index 955c465..4374db9 100644
> --- a/src/box/lua/space.cc
> +++ b/src/box/lua/space.cc
> @@ -34,6 +34,7 @@
>   #include "lua/utils.h"
>   #include "lua/trigger.h"
>   #include "box/box.h"
> +#include "box/lua/misc.h" /* lbox_encode_tuple_on_gc() */

12. Why? Please, go through your patches and check for unused
includes. I will not mention it anymore.

>   
>   extern "C" {
>   	#include <lua.h>
> @@ -616,6 +617,93 @@ lbox_space_delete_ephemeral(struct lua_State *L)
>   }
>   
>   /**
> + * Create an index for ephemeral space.
> + * @param Lua table - ephemeral space.
> + * @param Lua uint32_t id - id of index, for
> + * ephemeral spaces it is 0 as they can have only
> + * primary index.
> + * @param Lua const char *name - name of index.
> + * @param Lua const char *type_field - type of field.
> + * @param Lua const char *opts_field - options in
> + * msgpack format.
> + * @param Lua const char *parts - parts in msgpack
> + * format.
> + * @retval not nil - ephemeral space created.
> + * @retval nil - error, A reason is returned in
> + *         the second value.
> + */
> +static int
> +lbox_index_new_ephemeral(struct lua_State *L)
> +{
> +	uint32_t argc = lua_gettop(L);
> +	if (argc != 6)
> +		return luaL_error(L, "Using: ephemeral:create_index(opts");
> +	struct space *space = (struct space *)lua_checkephemeralspace(L, 1);
> +	uint32_t index_id = luaL_checknumber (L, 2);
> +	const char *name = luaL_checkstring (L, 3);
> +	const char *type_field = luaL_checkstring (L, 4);
> +	const char *opts_field = luaL_checkstring (L, 5);
> +	const char *parts = luaL_checkstring (L, 6);
> +	assert(index_id == 0);
> +	struct space_def *ephemeral_space_def = space_def_dup(space->def);

13. Please, remove '_ephemeral' suffix from variable names. They are too
long and it is hard to read this Java/C#-like code.

> +	if (ephemeral_space_def == NULL)
> +		return luaL_error(L, "Error with creating space_def");

14. Same as earlier - do not override Tarantool error with Lua one.
Use luaT_error. I will not mention it anymore, so, please, found and
fix other places.

> +	struct index_def *index_def_ephemeral =
> +		ephemeral_index_def(space, index_id, name, type_field,
> +				    opts_field, parts);
> +	if(index_def_ephemeral == NULL)
> +		return luaT_error(L);
> +	if(!index_def_is_valid(index_def_ephemeral, space_name(space)) ||
> +	   space_check_index_def(space, index_def_ephemeral) != 0) {
> +		index_def_delete(index_def_ephemeral);
> +		return luaT_error(L);
> +	}
> +	struct rlist key_list;
> +	rlist_create(&key_list);
> +	rlist_add_entry(&key_list, index_def_ephemeral, link);
> +	struct space *new_space = space_new_ephemeral(ephemeral_space_def,
> +						      &key_list);
> +	index_def_delete(index_def_ephemeral);
> +	space_def_delete(ephemeral_space_def);
> +	if(new_space == NULL) {
> +		return luaL_error(L, "Error with creating index for "\
> +				     "ephemeral space");
> +	}
> +	space_delete(space);
> +	struct space **ptr =
> +		(struct space **) luaL_pushcdata(L, CTID_STRUCT_SPACE_POINTER);
> +	*ptr = new_space;
> +	return 1;
> +}
> diff --git a/test/box/ephemeral_space.result b/test/box/ephemeral_space.result
> index 135df3c..d958ffe 100644
> --- a/test/box/ephemeral_space.result
> +++ b/test/box/ephemeral_space.result
> @@ -1,5 +1,5 @@
> --- Ephemeral space: creation and dropping
> --- Simple creation
> +-- Ephemeral space: creation and dropping.
> +-- Simple creation.

15. These spelling fixes should not be part of this patch.

>   s = box.schema.space.create_ephemeral()
>   ---
>   ...
> @@ -185,7 +185,218 @@ s
>   ---
>   - []
>   ...
> --- Ephemeral space: methods
> +-- Ephemeral space: index creation and dropping.
> +s = box.schema.space.create_ephemeral()
> +---
> +...
> +-- Simple creation
> +i = s:create_index('a')
> +---
> +...
> +i.unique
> +---
> +- true
> +...
> +i.parts
> +---
> +- - - 0
> +    - unsigned
> +...
> +i.id
> +---
> +- 0
> +...
> +i.name
> +---
> +- a
> +...
> +i:drop()
> +---
> +...
> +-- Double creation of index for ephemeral space.
> +i = s:create_index('a')
> +---
> +...
> +i = s:create_index('a')
> +---
> +- error: 'builtin/box/schema.lua:1145: Primary index for this ephemeral index already
> +    exists'

16. Please, use diag_set and ER_UNSUPPORTED for this type of errors.

> +...
> +i:drop()
> +---
> +...
> +-- Double creation of index for ephemeral space
> +-- but with if_not_exists=true.
> +i = s:create_index('a')
> +---
> +...
> +i = s:create_index('a', {if_not_exists=true})
> +---
> +...
> +i:drop()
> +---
> +...
> +-- Ephemeral space can have only primary.
> +-- index so its id == 0
> +i = s:create_index('a', {id = 10})
> +---
> +- error: 'builtin/box/schema.lua:1150: Ephemeral space can have only primary index.'
> +...
> +-- Set parameters: parts.
> +i = s:create_index('a', {parts={1}})
> +---
> +...
> +i.unique
> +---
> +- true

17. It is enough to just print the entire 'i'. Just write it alone on
the line. And it is not necessary to output the entire 'i' on each
'create_index'. Print just the attributes you have specified in the
options.

> +---
> +...
> +i = s:create_index('a', {parts={1,'uint',2,'int',3,'str'}})

18. Please, do not use 'uint' and 'str' - they are deprecated.

  reply	other threads:[~2018-07-13 16:32 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-12 11:16 [tarantool-patches] [PATCH 0/5] Expose ephemeral spaces into Lua imeevma
2018-07-12 11:16 ` [tarantool-patches] [PATCH 1/5] Create new methods for ephemeral spaces imeevma
2018-07-13 16:32   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-12 11:16 ` [tarantool-patches] [PATCH 2/5] Move some decode functions from alter.cc imeevma
2018-07-13 16:32   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-12 11:16 ` [tarantool-patches] [PATCH 3/5] Ephemeral space creation and deletion in Lua imeevma
2018-07-13 16:32   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-12 11:16 ` [tarantool-patches] [PATCH 4/5] Primary index for ephemeral spaces imeevma
2018-07-13 16:32   ` Vladislav Shpilevoy [this message]
2018-07-12 11:16 ` [tarantool-patches] [PATCH 5/5] Methods for ephemeral space and its index imeevma
2018-07-13 16:32   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-12 11:30 ` [tarantool-patches] Re: [PATCH 0/5] Expose ephemeral spaces into Lua Imeev Mergen

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=e0ea34bf-82b8-e703-ef53-c5fc7f6a173f@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=imeevma@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH 4/5] Primary index for ephemeral spaces' \
    /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