[Tarantool-patches] [PATCH] box: make box.execute() immutable

Igor Munkin imun at tarantool.org
Thu Mar 19 01:25:25 MSK 2020


Masha,

Thanks for the patch! I left a couple of comments below, please consider
them.

Side note: Sasha, there is much work done to solve the issue but we have
a ticket[1] requesting to drop the "feature". Could you please write a
rationale to proceed with this fix, instead of removing the implicit
box.cfg call from of box.execute?

On 11.03.20, Maria Khaydich wrote:
> 
> Thank you for the review! I reworked the patch:
> ----------------------------------------------------------------------
> Saving box.execute method before explicitly configuring box
> automatically invokes load_cfg() nonetheless. Further calls
> to box.cfg{} caused its reconfiguration and replacement of
> previously saved box.execute meaning it couldn't be used
> again without leading to an error.
>  
> The patch introduces a workaround making box.execute idempotent
> and is heavily influenced by @Totktonada.
>  
> Closes #4231
> ---
> Issue:
> https://github.com/tarantool/tarantool/issues/4231  
> Branch:
> https://github.com/tarantool/tarantool/compare/eljashm/gh-4231-box.execute-immutable-function  
>  
>  extra/exports                                 |  2 +
>  src/box/lua/load_cfg.lua                      | 42 ++++++++++++++++---
>  .../gh-4231-immutable-box-execute.test.lua    | 28 +++++++++++++
>  3 files changed, 67 insertions(+), 5 deletions(-)
>  create mode 100755 test/box-tap/gh-4231-immutable-box-execute.test.lua

<snipped>

> diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
> index 85617c8f0..dc4293bdd 100644
> --- a/src/box/lua/load_cfg.lua
> +++ b/src/box/lua/load_cfg.lua

<snipped>

> @@ -558,15 +564,41 @@ local function load_cfg(cfg)
>  end
>  box.cfg = locked(load_cfg)
>  
> +local function box_is_configured()
> +    return ffi.C.box_is_configured()
> +end
> +
>  --
> --- This makes possible do box.execute without calling box.cfg
> --- manually. The load_cfg call overwrites following table and
> --- metatable.
> +-- box.execute is <box_load_and_execute> when box is not loaded,
> +-- <lbox_execute> otherwise. See also <box_configured> variable.
> +-- <box_load_and_execute> loads box and calls <lbox_execute>.
>  --
> -function box.execute(...)
> -    load_cfg()
> +local box_load_and_execute
> +box_load_and_execute = function(...)
> +    -- Configure box if it is not configured, no-op otherwise (not
> +    -- reconfiguration).
> +    -- We should check whether box is configured, because a user
> +    -- may save <box_load_and_execute> function before box loading
> +    -- and call it afterwards.
> +    if not box_is_configured() then

It's better to use a sole function here instead of creating a new one
for every call.

> +        locked(function()
> +            -- Re-check, because after releasing of the lock the
> +            -- box state may be changed. We should call load_cfg()
> +            -- only once.
> +            if not box_is_configured() then
> +                load_cfg()
> +            end
> +        end)()
> +    end
> +
> +    -- At this point box should be configured and box.execute()
> +    -- function should be replaced with lbox_execute().
> +    assert(type(box.cfg) ~= 'function')
> +    assert(box.execute ~= box_load_and_execute)
> +
>      return box.execute(...)
>  end
> +box.execute = box_load_and_execute
>  
>  -- gh-810:
>  -- hack luajit default cpath
> diff --git a/test/box-tap/gh-4231-immutable-box-execute.test.lua b/test/box-tap/gh-4231-immutable-box-execute.test.lua

Minor: test chunk name is left unchanged since the previous version and
doesn't respect the commit message wording.

> new file mode 100755
> index 000000000..1544591bf
> --- /dev/null
> +++ b/test/box-tap/gh-4231-immutable-box-execute.test.lua
> @@ -0,0 +1,28 @@
> +#!/usr/bin/env tarantool
> +local tap = require('tap')
> +local test = tap.test('execute')
> +test:plan(2)
> +
> +--
> +-- gh-4231: box.execute should be an idempotent function
> +-- meaning its effect should be the same if a user chooses
> +-- to use it before explicit box.cfg invocation
> +--
> +
> +local function execute_is_immutable(execute, cmd, msg)

Typo: s/immutable/idempotent/.

> +    local status, err = pcall(execute, cmd)
> +    test:ok(status and type(err) == 'table', msg)
> +end
> +
> +local box_execute_stub = box.execute
> +-- explicit call to load_cfg
> +box.cfg{}
> +local box_execute_actual = box.execute
> +
> +execute_is_immutable(box_execute_stub,
> +    "CREATE TABLE t1 (s1 INTEGER, PRIMARY KEY (s1));",
> +    "box.execute stub works before box.cfg")
> +execute_is_immutable(box_execute_actual, "DROP TABLE t1",
> +    "box.execute works properly after box.cfg")
> +
> +os.exit(test:check() and 0 or 1)
> -- 
> 2.24.0 

<snipped>

>  
>  
> --
> Maria Khaydich
>  

[1]: https://github.com/tarantool/tarantool/issues/4726

-- 
Best regards,
IM


More information about the Tarantool-patches mailing list