From: Vladimir Davydov <vdavydov.dev@gmail.com>
To: Kirill Shcherbatov <kshcherbatov@tarantool.org>
Cc: tarantool-patches@freelists.org
Subject: Re: [PATCH v3 3/6] box: rework func object as a function frontend
Date: Tue, 18 Jun 2019 16:23:20 +0300 [thread overview]
Message-ID: <20190618132320.r2vtyk2hprogwd6s@esperanza> (raw)
In-Reply-To: <536bcc9ce5085679877fa91cea36f021168ffc2b.1560433806.git.kshcherbatov@tarantool.org>
On Thu, Jun 13, 2019 at 05:08:23PM +0300, Kirill Shcherbatov wrote:
> The function func object used to provide a call method only for
> C functions. In scope of this patch it reworked to be a uniform
> function call frontend both for C and Lua functions.
>
> Introduced classes func_c and func_lua, that provide own
> constructors which produce implementation-specific object with
> call and destroy methods.
>
> Needed for #4182, #1260
> ---
> src/box/alter.cc | 1 +
> src/box/call.c | 105 ++---------------------------
> src/box/func.c | 165 ++++++++++++++++++++++++++++++++++++++++-----
> src/box/func.h | 25 ++++---
> src/box/func_def.h | 2 +
> src/box/lua/call.c | 46 +++++++++++++
> src/box/lua/call.h | 5 ++
> src/box/session.cc | 11 ++-
> src/box/session.h | 8 +++
> 9 files changed, 235 insertions(+), 133 deletions(-)
Generally, the patch is fine. See some minor comments inline.
> diff --git a/src/box/func.c b/src/box/func.c
> index 740fad3d7..20ff56668 100644
> --- a/src/box/func.c
> +++ b/src/box/func.c
> @@ -381,19 +409,39 @@ func_new(struct func_def *def)
> * checks (see user_has_data()).
> */
> func->owner_credentials.auth_token = BOX_USER_MAX; /* invalid value */
> + return func;
> +}
> +
> +static struct func_vtab func_c_vtab;
> +
> +struct func *
> +func_c_new(struct func_def *def)
Nit: should be static.
> +{
> + (void) def;
> + assert(def->language == FUNC_LANGUAGE_C);
> + struct func_c *func = (struct func_c *) malloc(sizeof(struct func_c));
> + if (func == NULL) {
> + diag_set(OutOfMemory, sizeof(*func), "malloc", "func");
> + return NULL;
> + }
> + func->base.vtab = &func_c_vtab;
> func->func = NULL;
> func->module = NULL;
> - return func;
> + return &func->base;
> }
>
> static void
> -func_unload(struct func *func)
> +func_c_unload(struct func *base)
> {
> + assert(base->vtab == &func_c_vtab);
> + assert(base != NULL && base->def->language == FUNC_LANGUAGE_C);
> + struct func_c *func = (struct func_c *) base;
> +
> if (func->module) {
> rlist_del(&func->item);
> if (rlist_empty(&func->module->funcs)) {
> struct func_name name;
> - func_split_name(func->def->name, &name);
> + func_split_name(func->base.def->name, &name);
> module_cache_del(name.package, name.package_end);
> }
> module_gc(func->module);
> @@ -407,12 +455,15 @@ func_unload(struct func *func)
> * symbol from it).
> */
> static int
> -func_load(struct func *func)
> +func_c_load(struct func *base)
Why does it take struct func? Why not struct func_c?
> {
> + assert(base->vtab == &func_c_vtab);
> + assert(base != NULL && base->def->language == FUNC_LANGUAGE_C);
> + struct func_c *func = (struct func_c *) base;
> assert(func->func == NULL);
>
> struct func_name name;
> - func_split_name(func->def->name, &name);
> + func_split_name(func->base.def->name, &name);
>
> struct module *module = module_cache_find(name.package,
> name.package_end);
> @@ -472,10 +526,87 @@ func_call(struct func *func, struct port *in_port, struct port *out_port)
> return rc;
> }
>
> +static struct func_vtab func_c_vtab = {
> + .call = func_c_call,
> + .destroy = func_c_unload,
This looks confusing. Let's call the destructor 'func_c_destroy'.
Also, I think that free(func) should be called not by the generic
func_destroy(), but by the virtual destructor, because it's good
to have malloc and free in the same compilation unit.
I like func_c_load/func_c_unload symmetry. Let's make those functions
take struct func_c instead of struct func. Then func_c_destroy would
call func_c_unload and free struct func.
> +};
> +
> void
> func_delete(struct func *func)
> {
> - func_unload(func);
> + func->vtab->destroy(func);
> free(func->def);
> free(func);
> }
> +
> +/** Check "EXECUTE" permissions for a given function. */
> +static int
> +func_access_check(struct func *base)
Nit: since you don't cast it to a subclass, better name it simply
'func', not 'base' IMO.
> +{
> + struct credentials *credentials = effective_user();
> + /*
> + * If the user has universal access, don't bother with
> + * checks. No special check for ADMIN user is necessary
> + * since ADMIN has universal access.
> + */
> + if ((credentials->universal_access & (PRIV_X | PRIV_U)) ==
> + (PRIV_X | PRIV_U))
> + return 0;
> + user_access_t access = PRIV_X | PRIV_U;
> + /* Check access for all functions. */
> + access &= ~entity_access_get(SC_FUNCTION)[
> + credentials->auth_token].effective;
> + user_access_t func_access = access & ~credentials->universal_access;
> + if (/* Check for missing Usage access, ignore owner rights. */
> + func_access & PRIV_U ||
> + /* Check for missing specific access, respect owner rights. */
> + (base->def->uid != credentials->uid &&
> + func_access & ~base->access[credentials->auth_token].effective)) {
Nit: bad indentation: func_access... should be aligned by
the parenthesis.
> diff --git a/src/box/func.h b/src/box/func.h
> index d38a2b283..1271bde67 100644
> --- a/src/box/func.h
> +++ b/src/box/func.h
> @@ -62,24 +63,22 @@ struct module {
> bool is_unloading;
> };
>
> +/** Virtual method table for func object. */
> +struct func_vtab {
> + /** Call function with given arguments. */
> + int (*call)(struct func *func, struct port *in_port,
> + struct port *out_port);
> + /** Release implementation-specific function context. */
> + void (*destroy)(struct func *func);
> +};
> +
> /**
> * Stored function.
> */
> struct func {
> struct func_def *def;
> - /**
> - * Anchor for module membership.
> - */
> - struct rlist item;
> - /**
> - * For C functions, the body of the function.
> - */
> - box_function_f func;
> - /**
> - * Each stored function keeps a handle to the
> - * dynamic library for the C callback.
> - */
> - struct module *module;
> + /** Virtual method table. */
> + struct func_vtab *vtab;
Nit: should be const.
> diff --git a/src/box/lua/call.c b/src/box/lua/call.c
> index e32845095..8d0328ef7 100644
> --- a/src/box/lua/call.c
> +++ b/src/box/lua/call.c
> @@ -523,6 +525,50 @@ box_lua_eval(const char *expr, uint32_t expr_len,
> return box_process_lua(execute_lua_eval, &ctx, in_port, out_port);
> }
>
> +struct func_lua {
> + /** Function object base class. */
> + struct func base;
> +};
> +
> +static struct func_vtab func_lua_vtab;
> +
> +struct func *
> +func_lua_new(struct func_def *def)
> +{
> + (void) def;
> + assert(def->language == FUNC_LANGUAGE_LUA);
> + struct func_lua *func =
> + (struct func_lua *) malloc(sizeof(struct func_lua));
> + if (func == NULL) {
> + diag_set(OutOfMemory, sizeof(*func), "malloc", "func");
> + return NULL;
> + }
> + func->base.vtab = &func_lua_vtab;
> + return &func->base;
> +}
> +
> +static void
> +func_lua_unload(struct func *base)
Again, I think this should be called func_lua_destroy and this function
should free func_lua struct.
> +{
> + assert(base != NULL && base->def->language == FUNC_LANGUAGE_LUA);
> + assert(base->vtab == &func_lua_vtab);
> + (void) base;
> +}
> +
> +static inline int
> +func_lua_call(struct func *func, struct port *in_port, struct port *out_port)
> +{
> + assert(func != NULL && func->def->language == FUNC_LANGUAGE_LUA);
> + assert(func->vtab == &func_lua_vtab);
> + return box_lua_call(func->def->name, func->def->name_len,
> + in_port, out_port);
> +}
> +
> +static struct func_vtab func_lua_vtab = {
> + .call = func_lua_call,
> + .destroy = func_lua_unload,
> +};
> +
> static int
> lbox_module_reload(lua_State *L)
> {
> diff --git a/src/box/session.h b/src/box/session.h
> index 3a7397146..6bafb8561 100644
> --- a/src/box/session.h
> +++ b/src/box/session.h
> @@ -312,6 +312,14 @@ access_check_session(struct user *user);
> int
> access_check_universe(user_access_t access);
>
> +/**
> + * Check whether or not the current user can be granted
> + * the requested access to the universe object.
The comment is kinda confusing. Let's just say something like
Same as access_check_universe(), but in case the current user doesn't
have universal access, set AccessDeniedError for the given object type
and name.
> + */
> +int
> +access_check_universe_object(user_access_t access, enum schema_object_type type,
Nit: I'd s/type/object_type for consistency with object_name.
> + const char *object_name);
> +
> static inline int
> session_push(struct session *session, uint64_t sync, struct port *port)
> {
next prev parent reply other threads:[~2019-06-18 13:23 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-13 14:08 [PATCH v3 0/6] box: rework functions machinery Kirill Shcherbatov
2019-06-13 14:08 ` [PATCH v3 1/6] box: rework func cache update machinery Kirill Shcherbatov
2019-06-18 10:52 ` Vladimir Davydov
2019-06-19 15:51 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-13 14:08 ` [PATCH v3 2/6] box: rework box_lua_{call, eval} to use input port Kirill Shcherbatov
2019-06-17 9:35 ` [tarantool-patches] " Konstantin Osipov
2019-06-17 10:27 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-18 12:12 ` Vladimir Davydov
2019-06-19 15:51 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-19 16:11 ` Vladimir Davydov
2019-06-18 13:58 ` Vladimir Davydov
2019-06-19 18:28 ` [tarantool-patches] " Konstantin Osipov
2019-06-20 7:53 ` Kirill Shcherbatov
2019-06-20 8:09 ` Konstantin Osipov
2019-06-20 8:44 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-19 18:30 ` [tarantool-patches] " Konstantin Osipov
2019-06-13 14:08 ` [PATCH v3 3/6] box: rework func object as a function frontend Kirill Shcherbatov
2019-06-18 13:23 ` Vladimir Davydov [this message]
2019-06-19 15:51 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-13 14:08 ` [PATCH v3 4/6] box: export registered functions in box.func folder Kirill Shcherbatov
2019-06-18 14:06 ` Vladimir Davydov
2019-06-19 15:51 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-18 16:11 ` Vladimir Davydov
2019-06-13 14:08 ` [PATCH v3 5/6] box: refactor box_lua_find helper Kirill Shcherbatov
2019-06-18 14:22 ` Vladimir Davydov
2019-06-19 15:51 ` [tarantool-patches] " Kirill Shcherbatov
2019-06-13 14:08 ` [PATCH v3 6/6] box: introduce Lua persistent functions Kirill Shcherbatov
2019-06-18 16:23 ` Vladimir Davydov
2019-06-19 15:51 ` [tarantool-patches] " Kirill Shcherbatov
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=20190618132320.r2vtyk2hprogwd6s@esperanza \
--to=vdavydov.dev@gmail.com \
--cc=kshcherbatov@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='Re: [PATCH v3 3/6] box: rework func object as a function frontend' \
/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