From 5ab4800fc265a7d3526dd00ef6201af2ca7ffec9 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 7 Jul 2006 17:50:45 +0200 Subject: [PATCH] Bug #20897 race condition between drop table and suma drop trigger - keep accounting for aoutstanding drop trigger requests - also lock table object in suma while doing that (should be impossible right now though since dict serializes all requests) --- storage/ndb/src/kernel/blocks/suma/Suma.cpp | 53 ++++++++++++++------- storage/ndb/src/kernel/blocks/suma/Suma.hpp | 3 +- storage/ndb/src/ndbapi/ndberror.c | 2 + 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp index bb42c8874c5..2b746fdbdd8 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp @@ -1445,12 +1445,13 @@ Suma::initTable(Signal *signal, Uint32 tableId, TablePtr &tabPtr) tabPtr.p->m_error = 0; tabPtr.p->m_schemaVersion = RNIL; tabPtr.p->m_state = Table::DEFINING; - tabPtr.p->m_hasTriggerDefined[0] = 0; - tabPtr.p->m_hasTriggerDefined[1] = 0; - tabPtr.p->m_hasTriggerDefined[2] = 0; - tabPtr.p->m_triggerIds[0] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[1] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[2] = ILLEGAL_TRIGGER_ID; + tabPtr.p->m_drop_subbPtr.p = 0; + for (int j= 0; j < 3; j++) + { + tabPtr.p->m_hasTriggerDefined[j] = 0; + tabPtr.p->m_hasOutstandingTriggerReq[j] = 0; + tabPtr.p->m_triggerIds[j] = ILLEGAL_TRIGGER_ID; + } c_tables.add(tabPtr); @@ -2491,6 +2492,13 @@ Suma::execSUB_STOP_REQ(Signal* signal){ DBUG_VOID_RETURN; } + if (tabPtr.p->m_drop_subbPtr.p != 0) { + jam(); + DBUG_PRINT("error", ("table locked")); + sendSubStopRef(signal, 1420); + DBUG_VOID_RETURN; + } + DBUG_PRINT("info",("subscription: %u tableId: %u[i=%u] id: %u key: %u", subPtr.i, subPtr.p->m_tableId, tabPtr.i, subPtr.p->m_subscriptionId,subPtr.p->m_subscriptionKey)); @@ -2543,7 +2551,7 @@ Suma::execSUB_STOP_REQ(Signal* signal){ subPtr.p->m_senderRef = senderRef; // store ref to requestor subPtr.p->m_senderData = senderData; // store ref to requestor - tabPtr.p->m_drop_subbPtr= subbPtr; + tabPtr.p->m_drop_subbPtr = subbPtr; if (subPtr.p->m_state == Subscription::DEFINED) { @@ -2560,6 +2568,7 @@ Suma::execSUB_STOP_REQ(Signal* signal){ tabPtr.p->m_tableId, tabPtr.p->n_subscribers)); tabPtr.p->checkRelease(*this); sendSubStopComplete(signal, tabPtr.p->m_drop_subbPtr); + tabPtr.p->m_drop_subbPtr.p = 0; } else { @@ -2894,6 +2903,9 @@ Suma::Table::dropTrigger(Signal* signal,Suma& suma) jam(); DBUG_ENTER("Suma::dropTrigger"); + m_hasOutstandingTriggerReq[0] = + m_hasOutstandingTriggerReq[1] = + m_hasOutstandingTriggerReq[2] = 1; for(Uint32 j = 0; j<3; j++){ jam(); suma.suma_ndbrequire(m_triggerIds[j] != ILLEGAL_TRIGGER_ID); @@ -2972,14 +2984,18 @@ Suma::Table::runDropTrigger(Signal* signal, suma.suma_ndbrequire(type < 3); suma.suma_ndbrequire(m_triggerIds[type] == triggerId); + suma.suma_ndbrequire(m_hasTriggerDefined[type] > 0); + suma.suma_ndbrequire(m_hasOutstandingTriggerReq[type] == 1); m_hasTriggerDefined[type]--; + m_hasOutstandingTriggerReq[type] = 0; if (m_hasTriggerDefined[type] == 0) { jam(); m_triggerIds[type] = ILLEGAL_TRIGGER_ID; } - if( m_hasTriggerDefined[0] != m_hasTriggerDefined[1] || - m_hasTriggerDefined[0] != m_hasTriggerDefined[2]) + if( m_hasOutstandingTriggerReq[0] || + m_hasOutstandingTriggerReq[1] || + m_hasOutstandingTriggerReq[2]) { // more to come jam(); @@ -2997,6 +3013,7 @@ Suma::Table::runDropTrigger(Signal* signal, checkRelease(suma); suma.sendSubStopComplete(signal, m_drop_subbPtr); + m_drop_subbPtr.p = 0; } void Suma::suma_ndbrequire(bool v) { ndbrequire(v); } @@ -3551,13 +3568,17 @@ Suma::execDROP_TAB_CONF(Signal *signal) DBUG_PRINT("info",("drop table id: %d[i=%u]", tableId, tabPtr.i)); tabPtr.p->m_state = Table::DROPPED; - tabPtr.p->m_hasTriggerDefined[0] = 0; - tabPtr.p->m_hasTriggerDefined[1] = 0; - tabPtr.p->m_hasTriggerDefined[2] = 0; - tabPtr.p->m_triggerIds[0] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[1] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[2] = ILLEGAL_TRIGGER_ID; - + for (int j= 0; j < 3; j++) + { + if (!tabPtr.p->m_hasOutstandingTriggerReq[j]) + { + tabPtr.p->m_hasTriggerDefined[j] = 0; + tabPtr.p->m_hasOutstandingTriggerReq[j] = 0; + tabPtr.p->m_triggerIds[j] = ILLEGAL_TRIGGER_ID; + } + else + tabPtr.p->m_hasTriggerDefined[j] = 1; + } if (senderRef == 0) { DBUG_VOID_RETURN; diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.hpp b/storage/ndb/src/kernel/blocks/suma/Suma.hpp index 51f5fa4a8c8..4408d6aff8d 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.hpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.hpp @@ -301,7 +301,8 @@ public: union { Uint32 m_tableId; Uint32 key; }; Uint32 m_schemaVersion; - Uint32 m_hasTriggerDefined[3]; // Insert/Update/Delete + Uint8 m_hasTriggerDefined[3]; // Insert/Update/Delete + Uint8 m_hasOutstandingTriggerReq[3]; // Insert/Update/Delete Uint32 m_triggerIds[3]; // Insert/Update/Delete Uint32 m_error; diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c index 486d78538f0..d0d26c19cfa 100644 --- a/storage/ndb/src/ndbapi/ndberror.c +++ b/storage/ndb/src/ndbapi/ndberror.c @@ -484,6 +484,8 @@ ErrorBundle ErrorCodes[] = { { 1418, DMEC, SE, "Subscription dropped, no new subscribers allowed" }, { 1419, DMEC, SE, "Subscription already dropped" }, + { 1420, DMEC, TR, "Subscriber manager busy with adding/removing a table" }, + { 4004, DMEC, AE, "Attribute name not found in the Table" }, { 4100, DMEC, AE, "Status Error in NDB" },