Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: korablev@tarantool.org
Subject: [tarantool-patches] [PATCH 1/2] alter: do not access space in drop ck commit trigger
Date: Sat, 20 Jul 2019 00:49:40 +0200	[thread overview]
Message-ID: <4e8379b4d6a3c74b9da8af2cb99d132eae25a74c.1563576462.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1563576462.git.v.shpilevoy@tarantool.org>

When transactional DDL is introduced, 'DROP TABLE' will remove a
space and its cks in one transaction. At the moment of that
transaction commit the space is already removed from _space and
from space cache, and can't be accessed from other triggers.

This patch makes all space-related actions in on_replace.

Part of #4086
---
 src/box/alter.cc | 49 +++++++-----------------------------------------
 src/box/space.c  | 32 +++++++++++++++++++++++++++++++
 src/box/space.h  | 17 +++++++++++++++++
 3 files changed, 56 insertions(+), 42 deletions(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index e8721fd16..b3244094e 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -4526,17 +4526,10 @@ on_create_ck_constraint_rollback(struct trigger *trigger, void * /* event */)
 	assert(ck != NULL);
 	struct space *space = space_by_id(ck->def->space_id);
 	assert(space != NULL);
-	struct trigger *ck_trigger = space->ck_constraint_trigger;
-	assert(ck_trigger != NULL);
 	assert(space_ck_constraint_by_name(space, ck->def->name,
 					   strlen(ck->def->name)) != NULL);
-	rlist_del_entry(ck, link);
+	space_remove_ck_constraint(space, ck);
 	ck_constraint_delete(ck);
-	if (rlist_empty(&space->ck_constraint)) {
-		trigger_clear(ck_trigger);
-		ck_trigger->destroy(ck_trigger);
-		space->ck_constraint_trigger = NULL;
-	}
 	trigger_run_xc(&on_alter_space, space);
 }
 
@@ -4546,15 +4539,7 @@ on_drop_ck_constraint_commit(struct trigger *trigger, void * /* event */)
 {
 	struct ck_constraint *ck = (struct ck_constraint *)trigger->data;
 	assert(ck != NULL);
-	struct space *space = space_by_id(ck->def->space_id);
-	assert(space != NULL);
-	struct trigger *ck_trigger = space->ck_constraint_trigger;
-	assert(ck_trigger != NULL);
-	if (rlist_empty(&space->ck_constraint)) {
-		ck_trigger->destroy(ck_trigger);
-		space->ck_constraint_trigger = NULL;
-		ck_constraint_delete(ck);
-	}
+	ck_constraint_delete(ck);
 }
 
 /** Rollback DELETE check constraint. */
@@ -4565,13 +4550,10 @@ on_drop_ck_constraint_rollback(struct trigger *trigger, void * /* event */)
 	assert(ck != NULL);
 	struct space *space = space_by_id(ck->def->space_id);
 	assert(space != NULL);
-	struct trigger *ck_trigger = space->ck_constraint_trigger;
-	assert(ck_trigger != NULL);
 	assert(space_ck_constraint_by_name(space, ck->def->name,
 					   strlen(ck->def->name)) == NULL);
-	rlist_add_entry(&space->ck_constraint, ck, link);
-	if (rlist_empty(&ck_trigger->link))
-		trigger_add(&space->on_replace, ck_trigger);
+	if (space_add_ck_constraint(space, ck) != 0)
+		panic("Can't recover after CK constraint drop rollback");
 	trigger_run_xc(&on_alter_space, space);
 }
 
@@ -4613,8 +4595,6 @@ on_replace_dd_ck_constraint(struct trigger * /* trigger*/, void *event)
 		tuple_field_u32_xc(old_tuple != NULL ? old_tuple : new_tuple,
 				   BOX_CK_CONSTRAINT_FIELD_SPACE_ID);
 	struct space *space = space_cache_find_xc(space_id);
-	struct trigger *ck_trigger = space->ck_constraint_trigger;
-	assert(ck_trigger == NULL || !rlist_empty(&ck_trigger->link));
 	struct trigger *on_rollback = txn_alter_trigger_new(NULL, NULL);
 	struct trigger *on_commit = txn_alter_trigger_new(NULL, NULL);
 
@@ -4655,20 +4635,8 @@ on_replace_dd_ck_constraint(struct trigger * /* trigger*/, void *event)
 			space_ck_constraint_by_name(space, name, strlen(name));
 		if (old_ck_constraint != NULL)
 			rlist_del_entry(old_ck_constraint, link);
-		rlist_add_entry(&space->ck_constraint, new_ck_constraint, link);
-		if (ck_trigger == NULL) {
-			ck_trigger =
-				(struct trigger *)malloc(sizeof(*ck_trigger));
-			if (ck_trigger == NULL) {
-				tnt_raise(OutOfMemory, sizeof(*ck_trigger),
-					  "malloc", "ck_trigger");
-			}
-			trigger_create(ck_trigger,
-				       ck_constraint_on_replace_trigger, NULL,
-				       (trigger_f0) free);
-			trigger_add(&space->on_replace, ck_trigger);
-			space->ck_constraint_trigger = ck_trigger;
-		}
+		if (space_add_ck_constraint(space, new_ck_constraint) != 0)
+			diag_raise();
 		ck_guard.is_active = false;
 		if (old_tuple != NULL) {
 			on_rollback->data = old_ck_constraint;
@@ -4680,7 +4648,6 @@ on_replace_dd_ck_constraint(struct trigger * /* trigger*/, void *event)
 		on_commit->data = old_ck_constraint;
 		on_commit->run = on_replace_ck_constraint_commit;
 	} else {
-		assert(ck_trigger != NULL);
 		assert(new_tuple == NULL && old_tuple != NULL);
 		/* Drop check constraint. */
 		uint32_t name_len;
@@ -4691,9 +4658,7 @@ on_replace_dd_ck_constraint(struct trigger * /* trigger*/, void *event)
 		struct ck_constraint *old_ck_constraint =
 			space_ck_constraint_by_name(space, name, name_len);
 		assert(old_ck_constraint != NULL);
-		rlist_del_entry(old_ck_constraint, link);
-		if (rlist_empty(&space->ck_constraint))
-			trigger_clear(ck_trigger);
+		space_remove_ck_constraint(space, old_ck_constraint);
 		on_commit->data = old_ck_constraint;
 		on_commit->run = on_drop_ck_constraint_commit;
 		on_rollback->data = old_ck_constraint;
diff --git a/src/box/space.c b/src/box/space.c
index e7babb2ae..d81948ff3 100644
--- a/src/box/space.c
+++ b/src/box/space.c
@@ -545,6 +545,38 @@ space_execute_dml(struct space *space, struct txn *txn,
 	return 0;
 }
 
+int
+space_add_ck_constraint(struct space *space, struct ck_constraint *ck)
+{
+	rlist_add_entry(&space->ck_constraint, ck, link);
+	if (space->ck_constraint_trigger == NULL) {
+		struct trigger *ck_trigger =
+			(struct trigger *) malloc(sizeof(*ck_trigger));
+		if (ck_trigger == NULL) {
+			diag_set(OutOfMemory, sizeof(*ck_trigger), "malloc",
+				 "ck_trigger");
+			return -1;
+		}
+		trigger_create(ck_trigger, ck_constraint_on_replace_trigger,
+			       NULL, (trigger_f0) free);
+		trigger_add(&space->on_replace, ck_trigger);
+		space->ck_constraint_trigger = ck_trigger;
+	}
+	return 0;
+}
+
+void
+space_remove_ck_constraint(struct space *space, struct ck_constraint *ck)
+{
+	rlist_del_entry(ck, link);
+	if (rlist_empty(&space->ck_constraint)) {
+		struct trigger *ck_trigger = space->ck_constraint_trigger;
+		trigger_clear(ck_trigger);
+		ck_trigger->destroy(ck_trigger);
+		space->ck_constraint_trigger = NULL;
+	}
+}
+
 /* {{{ Virtual method stubs */
 
 size_t
diff --git a/src/box/space.h b/src/box/space.h
index 88db4ec52..708584968 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -50,6 +50,7 @@ struct request;
 struct port;
 struct tuple;
 struct tuple_format;
+struct ck_constraint;
 
 struct space_vtab {
 	/** Free a space instance. */
@@ -475,6 +476,22 @@ space_dump_def(const struct space *space, struct rlist *key_list);
 void
 space_fill_index_map(struct space *space);
 
+/**
+ * Add a new ck constraint to the space. A ck constraint check
+ * trigger is created, if this is a first ck in this space. The
+ * space takes ownership of this object.
+ */
+int
+space_add_ck_constraint(struct space *space, struct ck_constraint *ck);
+
+/**
+ * Remove a ck constraint from the space. A ck constraint check
+ * trigger is deleted, if this is a last ck in this space. This
+ * object may be deleted manually after the call.
+ */
+void
+space_remove_ck_constraint(struct space *space, struct ck_constraint *ck);
+
 /*
  * Virtual method stubs.
  */
-- 
2.20.1 (Apple Git-117)

  reply	other threads:[~2019-07-19 22:48 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-19 22:49 [tarantool-patches] [PATCH 0/2] SQL TXN DDL Vladislav Shpilevoy
2019-07-19 22:49 ` Vladislav Shpilevoy [this message]
2019-07-19 22:49 ` [tarantool-patches] [PATCH 2/2] sql: transactional DDL Vladislav Shpilevoy
2019-07-20  7:42   ` [tarantool-patches] " Konstantin Osipov
2019-07-20 14:02     ` Vladislav Shpilevoy
2019-07-20 15:16       ` Konstantin Osipov
2019-07-22 13:59   ` n.pettik
2019-07-22 21:35     ` Vladislav Shpilevoy
2019-07-24 13:23       ` n.pettik
2019-07-24 20:58         ` Vladislav Shpilevoy
2019-07-25 12:04           ` n.pettik
2019-07-31 13:19 ` [tarantool-patches] Re: [PATCH 0/2] SQL TXN DDL Kirill Yukhin

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=4e8379b4d6a3c74b9da8af2cb99d132eae25a74c.1563576462.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH 1/2] alter: do not access space in drop ck commit trigger' \
    /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