Tarantool development patches archive
 help / color / mirror / Atom feed
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)
>  {

  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