From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: Nikita Pettik <korablev@tarantool.org>, tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCH v2 06/10] box: introduce stacked diagnostic area Date: Sat, 28 Mar 2020 19:40:06 +0100 [thread overview] Message-ID: <f582e164-d623-a598-8feb-1ec08b7a00c9@tarantool.org> (raw) In-Reply-To: <d0a6aaffaaaea96d81a0cd006b9aeb762b2bcea7.1585097339.git.korablev@tarantool.org> Hi! Thanks for the patch! See 7 comments below. On 25/03/2020 02:43, Nikita Pettik wrote: > In terms of implementation, now struct error objects can be organized > into double-linked lists. To achieve this pointers to the next and > previous elements (cause and effort correspondingly) have been added to 1. effort -> effect. > struct error. It is worth mentioning that already existing rlist and > stailq list implementations are not suitable: rlist is cycled list, as a > result it is impossible to start iteration over the list from random > list entry and finish it at the logical end of the list; stailq is > single-linked list leaving no possibility to remove elements from the > middle of the list. > > diff --git a/src/box/key_list.c b/src/box/key_list.c > index 3d736b55f..81eb501a5 100644 > --- a/src/box/key_list.c > +++ b/src/box/key_list.c > @@ -64,7 +64,7 @@ key_list_iterator_create(struct key_list_iterator *it, struct tuple *tuple, > /* Can't evaluate function. */ > struct space *space = space_by_id(index_def->space_id); > diag_set(ClientError, ER_FUNC_INDEX_FUNC, index_def->name, > - space ? space_name(space) : "", > + space != NULL ? space_name(space) : "", > diag_last_error(diag_get())->errmsg); > return -1; > } > @@ -75,7 +75,7 @@ key_list_iterator_create(struct key_list_iterator *it, struct tuple *tuple, > struct space *space = space_by_id(index_def->space_id); > /* Can't get a result returned by function . */ > diag_set(ClientError, ER_FUNC_INDEX_FUNC, index_def->name, > - space ? space_name(space) : "", > + space != NULL ? space_name(space) : "", > diag_last_error(diag_get())->errmsg); > return -1; > } > diff --git a/src/box/lua/call.c b/src/box/lua/call.c > index f1bbde7f0..92575374d 100644 > --- a/src/box/lua/call.c > +++ b/src/box/lua/call.c > @@ -688,8 +688,8 @@ func_persistent_lua_load(struct func_lua *func) > if (prepare_lua_sandbox(tarantool_L, default_sandbox_exports, > nelem(default_sandbox_exports)) != 0) { > diag_set(ClientError, ER_LOAD_FUNCTION, > - func->base.def->name, > - diag_last_error(diag_get())->errmsg); > + func->base.def->name, > + diag_last_error(diag_get())->errmsg); > goto end; 2. Do you really need the 3 hunks above? Seems like unnecessary refactoring. > } > } else { > diff --git a/src/lib/core/diag.c b/src/lib/core/diag.c > index c350abb4a..57da5da44 100644 > --- a/src/lib/core/diag.c > +++ b/src/lib/core/diag.c > @@ -34,6 +34,43 @@ > /* Must be set by the library user */ > struct error_factory *error_factory = NULL; > > +int > +error_set_prev(struct error *e, struct error *prev) > +{ > + /* > + * Make sure that adding error won't result in cycles. > + * Don't bother with sophisticated cycle-detection > + * algorithms, simple iteration is OK since as a rule > + * list contains a dozen errors at maximum. > + */ > + struct error *tmp = prev; > + while (tmp != NULL) { > + if (tmp == e) > + return -1; > + tmp = tmp->cause; > + } 3. Or we could remove 'prev' from its current stack gracefully, since the list is doubly linked. Then cycles become impossible. Is there a reason not to do that? I mean, we remove 'prev' from its old stack by changing its 'effect' already anyway. Can do the same for the other pointer, and no need to check for cycles anymore. I can only think of a problem when someone makes e1 = box.error.new() e2 = box.error.new() e2:set_prev(e1) and then e4 = box.error.new() e4:set_prev(e1) assuming that e1 will be copied. But it will steal e1 from its old stack. Even with your current solution. Maybe to make it more protected against dummies we should forbid moving error from one stack to another? So an error can't change its 'cause' and 'effect' once they become not NULL. In that way we eliminate any uncertainties and in future can decide whether we want to copy in set_prev() when necessary, or move from previous stack. Or we will keep this forbidden because probably no one does moving between stacks, nor the example I showed above. This also significantly simplifies tests and reduces probability of having a bug there. What are your thoughts? > + /* > + * At once error can feature only one reason. > + * So unlink previous 'cause' node. > + */ > + if (e->cause != NULL) { > + e->cause->effect = NULL; > + error_unref(e->cause); > + } > + /* Set new 'prev' node. */ > + e->cause = prev; > + /* > + * Unlink new 'effect' node from its old list of 'cause' > + * errors. nil can be also passed as an argument. > + */ > + if (prev != NULL) { > + error_unlink_effect(prev); > + prev->effect = e; > + error_ref(prev); 4. Better call error_ref() before error_unlink_effect(). To make it impossible for prev to be deleted inside unlink() and be used after free. I can't find how can be it done now, but by moving ref() a bit above we will make it impossible in future as well. > + } > + return 0; > +} > diff --git a/src/lib/core/diag.h b/src/lib/core/diag.h > index 7e1e1a174..675b9c6f1 100644 > --- a/src/lib/core/diag.h > +++ b/src/lib/core/diag.h> @@ -96,11 +113,56 @@ static inline void > > +/** > + * Set previous error: cut @a prev from its previous 'tail' of > + * causes and link to the one @a e belongs to. Note that all > + * previous errors starting from @a prev->cause are transferred > + * with it as well (i.e. causes for given error are not erased). > + * For instance: > + * e1 -> e2 -> NULL; e3 -> e4 -> NULL; > + * e2:set_effect(e3): e1 -> e2 -> e3 -> e4 -> NULL > + * > + * @a effect can be NULL. To be used as ffi method in lua/error.lua. 5. Out of 66 and double whitespace before 'NULL'. > + * > + * @retval -1 in case adding @a effect results in list cycles; > + * 0 otherwise. > + */ > +int > +error_set_prev(struct error *e, struct error *prev); > + > diff --git a/test/box/error.result b/test/box/error.result > index a19a7044f..ff2b8b270 100644 > --- a/test/box/error.result > +++ b/test/box/error.result > @@ -502,6 +502,290 @@ box.error() > +-- In case error is destroyed, it unrefs reference counter > +-- of its previous error. In turn, box.error.clear() refs/unrefs > +-- only head and doesn't touch other errors. > +-- > +e2:set_prev(nil) > + | --- > + | ... > +box.error.set(e1) > + | --- > + | ... > +assert(box.error.last() == e1) > + | --- > + | - true > + | ... > +assert(box.error.last().prev == e2) > + | --- > + | - true > + | ... > +box.error.clear() > + | --- > + | ... > +assert(box.error.last() == nil) > + | --- > + | - true > + | ... > +assert(e1.prev == e2) > + | --- > + | - true > + | ... > +assert(e2.code == 111) 6. Double whitespace. Macbook keyboard, huh? > diff --git a/test/engine/func_index.result b/test/engine/func_index.result > index 84cb83022..159158f1c 100644 > --- a/test/engine/func_index.result > +++ b/test/engine/func_index.result > @@ -261,12 +261,6 @@ box.schema.func.create('runtimeerror', {body = lua_code, is_deterministic = true > idx = s:create_index('idx', {func = box.func.runtimeerror.id, parts = {{1, 'string'}}}) > | --- > | ... > -s:insert({1}) > - | --- > - | - error: 'Failed to build a key for functional index ''idx'' of space ''withdata'': > - | [string "return function(tuple) local ..."]:1: attempt to call > - | global ''require'' (a nil value)' > - | ... > idx:drop() 7. Why do you drop it here? The commit does not change any existing places setting errors. So it should not lead to any test changes. > | --- > | ...
next prev parent reply other threads:[~2020-03-28 18:40 UTC|newest] Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-03-25 1:42 [Tarantool-patches] [PATCH v2 00/10] Stacked diagnostics Nikita Pettik 2020-03-25 1:42 ` [Tarantool-patches] [PATCH v2 01/10] box: rfc for stacked diagnostic area Nikita Pettik 2020-03-25 8:27 ` Konstantin Osipov 2020-03-25 14:08 ` Nikita Pettik 2020-03-25 1:42 ` [Tarantool-patches] [PATCH v2 02/10] box: rename diag_add_error to diag_set_error Nikita Pettik 2020-03-25 8:27 ` Konstantin Osipov 2020-03-26 0:22 ` Vladislav Shpilevoy 2020-03-26 12:31 ` Nikita Pettik 2020-03-25 1:42 ` [Tarantool-patches] [PATCH v2 03/10] test: move box.error tests to box/error.test.lua Nikita Pettik 2020-03-25 8:28 ` Konstantin Osipov 2020-03-26 0:22 ` Vladislav Shpilevoy 2020-03-26 12:31 ` Nikita Pettik 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 04/10] box/error: introduce box.error.set() method Nikita Pettik 2020-03-25 8:33 ` Konstantin Osipov 2020-03-25 17:41 ` Nikita Pettik 2020-03-26 0:22 ` Vladislav Shpilevoy 2020-03-26 12:31 ` Nikita Pettik 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 05/10] box/error: don't set error created via box.error.new to diag Nikita Pettik 2020-03-26 16:50 ` Konstantin Osipov 2020-03-26 17:59 ` Nikita Pettik 2020-03-26 18:06 ` Nikita Pettik 2020-03-26 18:07 ` Alexander Turenko 2020-03-27 0:19 ` Vladislav Shpilevoy 2020-03-27 13:09 ` Nikita Pettik 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 06/10] box: introduce stacked diagnostic area Nikita Pettik 2020-03-26 16:54 ` Konstantin Osipov 2020-03-26 18:03 ` Nikita Pettik 2020-03-26 18:08 ` Konstantin Osipov 2020-03-28 18:40 ` Vladislav Shpilevoy [this message] 2020-04-01 16:09 ` Nikita Pettik 2020-04-02 0:29 ` Vladislav Shpilevoy 2020-04-02 17:42 ` Nikita Pettik 2020-04-02 22:20 ` Vladislav Shpilevoy 2020-04-03 1:54 ` Nikita Pettik 2020-04-03 23:17 ` Vladislav Shpilevoy 2020-03-28 18:59 ` Vladislav Shpilevoy 2020-03-31 17:44 ` Nikita Pettik 2020-04-02 0:29 ` Vladislav Shpilevoy 2020-04-02 14:16 ` Nikita Pettik 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 07/10] box: use stacked diagnostic area for functional indexes Nikita Pettik 2020-03-30 23:24 ` Vladislav Shpilevoy 2020-04-01 15:53 ` Nikita Pettik 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 08/10] box/error: clarify purpose of reference counting in struct error Nikita Pettik 2020-03-30 23:24 ` Vladislav Shpilevoy 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 09/10] iproto: refactor error encoding with mpstream Nikita Pettik 2020-03-30 23:24 ` Vladislav Shpilevoy 2020-04-01 15:54 ` Nikita Pettik 2020-03-25 1:43 ` [Tarantool-patches] [PATCH v2 10/10] iproto: support error stacked diagnostic area Nikita Pettik 2020-03-30 23:24 ` Vladislav Shpilevoy 2020-04-01 16:26 ` Nikita Pettik 2020-04-01 22:24 ` Nikita Pettik 2020-04-02 0:29 ` Vladislav Shpilevoy 2020-04-02 14:01 ` Nikita Pettik 2020-04-02 22:20 ` Vladislav Shpilevoy 2020-04-03 2:16 ` Nikita Pettik 2020-04-03 23:17 ` Vladislav Shpilevoy 2020-04-06 11:07 ` Nikita Pettik
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=f582e164-d623-a598-8feb-1ec08b7a00c9@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=korablev@tarantool.org \ --cc=tarantool-patches@dev.tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v2 06/10] box: introduce stacked diagnostic area' \ /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