diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 7a3ecc5c090a9143618496085bb16615442e567f..fd17c3e26a698496e54bb6269682c31009eafe21 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -2659,25 +2659,63 @@ checkSchemaStatus(Uint32 tableType, Uint32 pass) case DictTabInfo::IndexTrigger: return false; case DictTabInfo::LogfileGroup: - return pass == 0; + return pass == 0 || pass == 9 || pass == 10; case DictTabInfo::Tablespace: - return pass == 1; + return pass == 1 || pass == 8 || pass == 11; case DictTabInfo::Datafile: case DictTabInfo::Undofile: - return pass == 2; + return pass == 2 || pass == 7 || pass == 12; case DictTabInfo::SystemTable: case DictTabInfo::UserTable: - return pass == 3; + return /* pass == 3 || pass == 6 || */ pass == 13; case DictTabInfo::UniqueHashIndex: case DictTabInfo::HashIndex: case DictTabInfo::UniqueOrderedIndex: case DictTabInfo::OrderedIndex: - return pass == 4; + return /* pass == 4 || pass == 5 || */ pass == 14; } return false; } +static const Uint32 CREATE_OLD_PASS = 4; +static const Uint32 DROP_OLD_PASS = 9; +static const Uint32 CREATE_NEW_PASS = 14; +static const Uint32 LAST_PASS = 14; + +NdbOut& +operator<<(NdbOut& out, const SchemaFile::TableEntry entry) +{ + out << "["; + out << " state: " << entry.m_tableState; + out << " version: " << hex << entry.m_tableVersion << dec; + out << " type: " << entry.m_tableType; + out << " words: " << entry.m_info_words; + out << " gcp: " << entry.m_gcp; + out << " ]"; + return out; +} + +/** + * Pass 0 Create old LogfileGroup + * Pass 1 Create old Tablespace + * Pass 2 Create old Datafile/Undofile + * Pass 3 Create old Table // NOT DONE DUE TO DIH + * Pass 4 Create old Index // NOT DONE DUE TO DIH + + * Pass 5 Drop old Index // NOT DONE DUE TO DIH + * Pass 6 Drop old Table // NOT DONE DUE TO DIH + * Pass 7 Drop old Datafile/Undofile + * Pass 8 Drop old Tablespace + * Pass 9 Drop old Logfilegroup + + * Pass 10 Create new LogfileGroup + * Pass 11 Create new Tablespace + * Pass 12 Create new Datafile/Undofile + * Pass 13 Create new Table + * Pass 14 Create new Index + */ + void Dbdict::checkSchemaStatus(Signal* signal) { XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0]; @@ -2692,287 +2730,132 @@ void Dbdict::checkSchemaStatus(Signal* signal) Uint32 tableId = c_restartRecord.activeTable; SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId); SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId); - SchemaFile::TableState schemaState = + SchemaFile::TableState newSchemaState = (SchemaFile::TableState)newEntry->m_tableState; SchemaFile::TableState oldSchemaState = (SchemaFile::TableState)oldEntry->m_tableState; if (c_restartRecord.activeTable >= c_tableRecordPool.getSize()) { jam(); - ndbrequire(schemaState == SchemaFile::INIT); + ndbrequire(newSchemaState == SchemaFile::INIT); ndbrequire(oldSchemaState == SchemaFile::INIT); continue; }//if - if(!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass)) - continue; - - if(!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass)) - continue; +//#define PRINT_SCHEMA_RESTART +#ifdef PRINT_SCHEMA_RESTART + char buf[100]; + snprintf(buf, sizeof(buf), "checkSchemaStatus: pass: %d table: %d", + c_restartRecord.m_pass, tableId); +#endif - switch(schemaState){ - case SchemaFile::INIT:{ - jam(); - bool ok = false; - switch(oldSchemaState) { - case SchemaFile::INIT: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED: - jam(); - ok = true; - jam(); - break; - - case SchemaFile::ADD_STARTED: - jam(); - case SchemaFile::TABLE_ADD_COMMITTED: - jam(); - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::ALTER_TABLE_COMMITTED: - jam(); - ok = true; - jam(); - newEntry->m_tableState = SchemaFile::INIT; - restartDropTab(signal, tableId); - return; + if (c_restartRecord.m_pass <= CREATE_OLD_PASS) + { + if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass)) + continue; - case SchemaFile::TEMPORARY_TABLE_COMMITTED: - // Temporary table is never written to disk, so just set to INIT. - jam(); - ok = true; - newEntry->m_tableState = SchemaFile::INIT; - break; - }//switch - ndbrequire(ok); - break; - } - case SchemaFile::ADD_STARTED:{ - jam(); - bool ok = false; - switch(oldSchemaState) { - case SchemaFile::INIT: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED: - jam(); - ok = true; - break; - case SchemaFile::ADD_STARTED: - jam(); - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::TABLE_ADD_COMMITTED: - jam(); - case SchemaFile::ALTER_TABLE_COMMITTED: + switch(oldSchemaState){ + case SchemaFile::INIT: jam(); + case SchemaFile::DROP_TABLE_COMMITTED: jam(); + case SchemaFile::ADD_STARTED: jam(); + case SchemaFile::DROP_TABLE_STARTED: jam(); + case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam(); + continue; + case SchemaFile::TABLE_ADD_COMMITTED: jam(); + case SchemaFile::ALTER_TABLE_COMMITTED: jam(); jam(); - ok = true; - //------------------------------------------------------------------ - // Add Table was started but not completed. Will be dropped in all - // nodes. Update schema information (restore table version). - //------------------------------------------------------------------ - newEntry->m_tableState = SchemaFile::INIT; - restartDropTab(signal, tableId); - return; - case SchemaFile::TEMPORARY_TABLE_COMMITTED: - jam(); - ok = true; - newEntry->m_tableState = SchemaFile::INIT; - break; +#ifdef PRINT_SCHEMA_RESTART + ndbout_c("%s -> restartCreateTab", buf); + ndbout << *newEntry << " " << *oldEntry << endl; +#endif + restartCreateTab(signal, tableId, oldEntry, oldEntry, true); + return; } - ndbrequire(ok); - break; } - case SchemaFile::TABLE_ADD_COMMITTED:{ - jam(); - bool ok = false; - switch(oldSchemaState) { - case SchemaFile::INIT: - jam(); - case SchemaFile::ADD_STARTED: - jam(); - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED: - jam(); - ok = true; - //------------------------------------------------------------------ - // Table was added in the master node but not in our node. We can - // retrieve the table definition from the master. - //------------------------------------------------------------------ - restartCreateTab(signal, tableId, oldEntry, newEntry, false); - return; - break; - case SchemaFile::TABLE_ADD_COMMITTED: - jam(); - case SchemaFile::ALTER_TABLE_COMMITTED: - jam(); - ok = true; - //------------------------------------------------------------------ - // Table was added in both our node and the master node. We can - // retrieve the table definition from our own disk. - //------------------------------------------------------------------ - if(newEntry->m_tableVersion == oldEntry->m_tableVersion) - { - jam(); - ndbrequire(newEntry->m_gcp == oldEntry->m_gcp); - ndbrequire(newEntry->m_tableType == oldEntry->m_tableType); - Uint32 type= oldEntry->m_tableType; - // On NR get index from master because index state is not on file - const bool file = c_systemRestart || !DictTabInfo::isIndex(type); - newEntry->m_info_words= oldEntry->m_info_words; - restartCreateTab(signal, tableId, oldEntry, newEntry, file); - return; - } else { - //------------------------------------------------------------------ - // Must be a new version of the table if anything differs. Both table - // version and global checkpoint must be different. - // This should not happen for the master node. This can happen after - // drop table followed by add table or after change table. - // Not supported in this version. - //------------------------------------------------------------------ - ndbrequire(c_masterNodeId != getOwnNodeId()); - ndbrequire(newEntry->m_tableVersion != oldEntry->m_tableVersion); - jam(); - - restartCreateTab(signal, tableId, oldEntry, newEntry, false); - return; - }//if - case SchemaFile::TEMPORARY_TABLE_COMMITTED: - jam(); - ok = true; - // For NR, we must re-create the table. - // For SR, we do nothing as the table was never saved to disk. - if(!c_systemRestart) + if (c_restartRecord.m_pass <= DROP_OLD_PASS) + { + if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass)) + continue; + + switch(oldSchemaState){ + case SchemaFile::INIT: jam(); + case SchemaFile::DROP_TABLE_COMMITTED: jam(); + case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam(); + continue; + case SchemaFile::ADD_STARTED: jam(); + case SchemaFile::DROP_TABLE_STARTED: jam(); +#ifdef PRINT_SCHEMA_RESTART + ndbout_c("%s -> restartDropTab", buf); + ndbout << *newEntry << " " << *oldEntry << endl; +#endif + restartDropTab(signal, tableId, oldEntry, newEntry); + return; + case SchemaFile::TABLE_ADD_COMMITTED: jam(); + case SchemaFile::ALTER_TABLE_COMMITTED: jam(); + if (! (* oldEntry == * newEntry)) { - restartCreateTab(signal, tableId, oldEntry, newEntry, false); +#ifdef PRINT_SCHEMA_RESTART + ndbout_c("%s -> restartDropTab", buf); + ndbout << *newEntry << " " << *oldEntry << endl; +#endif + restartDropTab(signal, tableId, oldEntry, newEntry); return; } - break; - } - ndbrequire(ok); - break; - } - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED:{ - jam(); - bool ok = false; - switch(oldSchemaState){ - case SchemaFile::INIT: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED: - jam(); - ok = true; - break; - case SchemaFile::ADD_STARTED: - jam(); - case SchemaFile::TABLE_ADD_COMMITTED: - jam(); - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::ALTER_TABLE_COMMITTED: - jam(); - newEntry->m_tableState = SchemaFile::INIT; - restartDropTab(signal, tableId); - return; - case SchemaFile::TEMPORARY_TABLE_COMMITTED: - jam(); - ok = true; - newEntry->m_tableState = SchemaFile::INIT; - break; + continue; } - ndbrequire(ok); - break; } - case SchemaFile::ALTER_TABLE_COMMITTED: { - jam(); - bool ok = false; - switch(oldSchemaState) { - case SchemaFile::INIT: - jam(); - case SchemaFile::ADD_STARTED: - jam(); - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED: - jam(); - case SchemaFile::TEMPORARY_TABLE_COMMITTED: - jam(); - ok = true; - if(!c_systemRestart) + + if (c_restartRecord.m_pass <= CREATE_NEW_PASS) + { + if (!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass)) + continue; + + switch(newSchemaState){ + case SchemaFile::INIT: jam(); + case SchemaFile::DROP_TABLE_COMMITTED: jam(); + case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam(); + * oldEntry = * newEntry; + continue; + case SchemaFile::ADD_STARTED: jam(); + case SchemaFile::DROP_TABLE_STARTED: jam(); + ndbrequire(false); + return; + case SchemaFile::TABLE_ADD_COMMITTED: jam(); + case SchemaFile::ALTER_TABLE_COMMITTED: jam(); + if (DictTabInfo::isIndex(newEntry->m_tableType) || + DictTabInfo::isTable(newEntry->m_tableType)) { - restartCreateTab(signal, tableId, oldEntry, newEntry, false); + bool file = * oldEntry == *newEntry && + (!DictTabInfo::isIndex(newEntry->m_tableType) || c_systemRestart); + +#ifdef PRINT_SCHEMA_RESTART + ndbout_c("%s -> restartCreateTab (file: %d)", buf, file); + ndbout << *newEntry << " " << *oldEntry << endl; +#endif + restartCreateTab(signal, tableId, newEntry, newEntry, file); + * oldEntry = * newEntry; return; } - break; - case SchemaFile::TABLE_ADD_COMMITTED: - jam(); - ok = true; - //------------------------------------------------------------------ - // Table was altered in the master node but not in our node. We can - // retrieve the altered table definition from the master. - //------------------------------------------------------------------ - restartCreateTab(signal, tableId, oldEntry, newEntry, false); - return; - break; - case SchemaFile::ALTER_TABLE_COMMITTED: - jam(); - ok = true; - - //------------------------------------------------------------------ - // Table was altered in both our node and the master node. We can - // retrieve the table definition from our own disk. - //------------------------------------------------------------------ - - // On NR get index from master because index state is not on file - Uint32 type= oldEntry->m_tableType; - const bool file = (* newEntry == * oldEntry) && - (c_systemRestart || !DictTabInfo::isIndex(type)); - newEntry->m_info_words= oldEntry->m_info_words; - restartCreateTab(signal, tableId, oldEntry, newEntry, file); - return; - } - ndbrequire(ok); - break; - } - case SchemaFile::TEMPORARY_TABLE_COMMITTED: { - jam(); - bool ok = false; - switch(oldSchemaState){ - case SchemaFile::INIT: - jam(); - case SchemaFile::DROP_TABLE_COMMITTED: - jam(); - case SchemaFile::ADD_STARTED: - jam(); - case SchemaFile::TABLE_ADD_COMMITTED: - jam(); - case SchemaFile::DROP_TABLE_STARTED: - jam(); - case SchemaFile::ALTER_TABLE_COMMITTED: - jam(); - case SchemaFile::TEMPORARY_TABLE_COMMITTED: - jam(); - ok = true; - if(!c_systemRestart) + else if (! (* oldEntry == *newEntry)) { - restartCreateTab(signal, tableId, oldEntry, newEntry, false); +#ifdef PRINT_SCHEMA_RESTART + ndbout_c("%s -> restartCreateTab", buf); + ndbout << *newEntry << " " << *oldEntry << endl; +#endif + restartCreateTab(signal, tableId, oldEntry, newEntry, false); + * oldEntry = * newEntry; return; - } else { - newEntry->m_tableState = SchemaFile::INIT; - } - break; + } + * oldEntry = * newEntry; + continue; } - ndbrequire(ok); - break; - } } } c_restartRecord.m_pass++; c_restartRecord.activeTable= 0; - if(c_restartRecord.m_pass <= 4) + if(c_restartRecord.m_pass <= LAST_PASS) { checkSchemaStatus(signal); } @@ -3299,7 +3182,33 @@ Dbdict::releaseCreateTableOp(Signal* signal, CreateTableRecordPtr createTabPtr) } void -Dbdict::restartDropTab(Signal* signal, Uint32 tableId){ +Dbdict::restartDropTab(Signal* signal, Uint32 tableId, + const SchemaFile::TableEntry * old_entry, + const SchemaFile::TableEntry * new_entry) +{ + switch(old_entry->m_tableType){ + case DictTabInfo::UndefTableType: + case DictTabInfo::HashIndexTrigger: + case DictTabInfo::SubscriptionTrigger: + case DictTabInfo::ReadOnlyConstraint: + case DictTabInfo::IndexTrigger: + ndbrequire(false); + case DictTabInfo::SystemTable: + case DictTabInfo::UserTable: + case DictTabInfo::UniqueHashIndex: + case DictTabInfo::HashIndex: + case DictTabInfo::UniqueOrderedIndex: + case DictTabInfo::OrderedIndex: + break; + case DictTabInfo::Tablespace: + case DictTabInfo::LogfileGroup: + case DictTabInfo::Datafile: + case DictTabInfo::Undofile: + warningEvent("Dont drop object: %d", tableId); + c_restartRecord.activeTable++; + checkSchemaStatus(signal); + return; + } const Uint32 key = ++c_opRecordSequence; @@ -3333,6 +3242,7 @@ Dbdict::restartDropTab_complete(Signal* signal, //@todo check error + releaseTableObject(c_restartRecord.activeTable); c_opDropTable.release(dropTabPtr); c_restartRecord.activeTable++; diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index 839d139a6591e1f3e0d1e1800fd8fd2e014371a6..2bb86a593be259cf68eb57f8cf03f6335b90349f 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -2551,7 +2551,9 @@ private: void restartCreateTab_dihComplete(Signal* signal, Uint32 callback, Uint32); void restartCreateTab_activateComplete(Signal*, Uint32 callback, Uint32); - void restartDropTab(Signal* signal, Uint32 tableId); + void restartDropTab(Signal* signal, Uint32 tableId, + const SchemaFile::TableEntry *, + const SchemaFile::TableEntry *); void restartDropTab_complete(Signal*, Uint32 callback, Uint32); void restart_checkSchemaStatusComplete(Signal*, Uint32 callback, Uint32);