Refactor and fix repository upgrade code
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/commit/1cfc0ed8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/tree/1cfc0ed8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafodion/diff/1cfc0ed8 Branch: refs/heads/master Commit: 1cfc0ed8bcaa9c3953d702429a406a8c4635b61c Parents: a49afa1 Author: Dave Birdsall <[email protected]> Authored: Wed Jul 13 18:42:53 2016 +0000 Committer: Dave Birdsall <[email protected]> Committed: Wed Jul 13 18:42:53 2016 +0000 ---------------------------------------------------------------------- core/sql/sqlcomp/CmpSeabaseDDL.h | 10 +- core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp | 160 ++++++++++++++---- core/sql/sqlcomp/CmpSeabaseDDLupgrade.cpp | 225 +++++++++++++++++++++---- core/sql/sqlcomp/CmpSeabaseDDLupgrade.h | 193 ++++++++++++++++++++- 4 files changed, 517 insertions(+), 71 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/1cfc0ed8/core/sql/sqlcomp/CmpSeabaseDDL.h ---------------------------------------------------------------------- diff --git a/core/sql/sqlcomp/CmpSeabaseDDL.h b/core/sql/sqlcomp/CmpSeabaseDDL.h index 21f5cbe..a00a7ec 100644 --- a/core/sql/sqlcomp/CmpSeabaseDDL.h +++ b/core/sql/sqlcomp/CmpSeabaseDDL.h @@ -1286,10 +1286,18 @@ protected: short createRepos(ExeCliInterface * cliInterface); short dropRepos(ExeCliInterface * cliInterface, - NABoolean oldRepos = FALSE, NABoolean dropSchema = TRUE); + NABoolean oldRepos = FALSE, NABoolean dropSchema = TRUE, + NABoolean inRecovery = FALSE); short alterRenameRepos(ExeCliInterface * cliInterface, NABoolean newToOld); short copyOldReposToNew(ExeCliInterface * cliInterface); + +public: + short upgradeRepos(ExeCliInterface * cliInterface, CmpDDLwithStatusInfo *mdui); + short upgradeReposComplete(ExeCliInterface * cliInterface, CmpDDLwithStatusInfo *mdui); + short upgradeReposUndo(ExeCliInterface * cliInterface, CmpDDLwithStatusInfo *mdui); + +protected: void processRepository(NABoolean createR, NABoolean dropR, NABoolean upgradeR); http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/1cfc0ed8/core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp ---------------------------------------------------------------------- diff --git a/core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp b/core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp index bc39c8d..f4704ea 100644 --- a/core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp +++ b/core/sql/sqlcomp/CmpSeabaseDDLrepos.cpp @@ -137,7 +137,8 @@ short CmpSeabaseDDL::createRepos(ExeCliInterface * cliInterface) short CmpSeabaseDDL::dropRepos(ExeCliInterface * cliInterface, NABoolean oldRepos, - NABoolean dropSchema) + NABoolean dropSchema, + NABoolean inRecovery) { Lng32 cliRC = 0; NABoolean xnWasStartedHere = FALSE; @@ -147,6 +148,13 @@ short CmpSeabaseDDL::dropRepos(ExeCliInterface * cliInterface, { const MDUpgradeInfo &rti = allReposUpgradeInfo[i]; + // If we are dropping the new repository as part of a recovery action, + // and there is no "old" table (because the table didn't change in this + // upgrade), then don't drop the new table. (If we did, we would be + // dropping the existing data.) + if (!oldRepos && inRecovery && !rti.oldName) + continue; + if ((oldRepos && !rti.oldName) || (NOT oldRepos && ! rti.newName)) continue; @@ -361,7 +369,7 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, { case 0: { - mdui->setMsg("Upgrade Repository: started"); + mdui->setMsg("Upgrade Repository: Started"); mdui->subStep()++; mdui->setEndStep(FALSE); @@ -383,7 +391,10 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, { // drop old repository if (dropRepos(cliInterface, TRUE/*old repos*/, FALSE/*no schema drop*/)) - return -1; + return -3; // error, but no recovery needed (and in fact + // doing such things as dropping the *new* repository + // would just destroy the existing repository data + // that we wish to save) mdui->setMsg(" End: Drop Old Repository"); mdui->subStep()++; @@ -407,10 +418,7 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, { // rename current repository tables to *_OLD_REPOS if (alterRenameRepos(cliInterface, TRUE)) - { - mdui->setSubstep(12); // label_error1 - break; - } + return -2; // error, need to undo the rename only mdui->setMsg(" End: Rename Current Repository"); mdui->subStep()++; @@ -434,10 +442,7 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, { // create new repository if (createRepos(cliInterface)) - { - mdui->setSubstep(13); // label_error2 - break; - } + return -1; // error, need to drop new repository then undo rename mdui->setMsg(" End: Create New Repository"); mdui->subStep()++; @@ -461,10 +466,7 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, { // copy old contents into new repository if (copyOldReposToNew(cliInterface)) - { - mdui->setSubstep(13); // label_error2 - break; - } + return -1; // error, need to drop new repository then undo rename mdui->setMsg(" End: Copy Old Repository Contents "); mdui->subStep()++; @@ -473,10 +475,38 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, return 0; } break; - + case 9: { - mdui->setMsg(" Start: Drop Old Repository "); + mdui->setMsg("Upgrade Repository: Done except for cleaning up"); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); + + return 0; + } + break; + + default: + return -1; + } + } // while + + return 0; +} + + +short CmpSeabaseDDL::upgradeReposComplete(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo *mdui) +{ + Lng32 cliRC = 0; + + while (1) // exit via return stmt in switch + { + switch (mdui->subStep()) + { + case 0: + { + mdui->setMsg("Upgrade Repository: Drop Old Repository"); mdui->subStep()++; mdui->setEndStep(FALSE); @@ -484,47 +514,105 @@ short CmpSeabaseDDL::upgradeRepos(ExeCliInterface * cliInterface, } break; - case 10: + case 1: { - // drop old repository + // drop old repository; ignore errors dropRepos(cliInterface, TRUE/*old repos*/, FALSE/*no schema drop*/); - mdui->setMsg(" End: Drop Old Repository"); + mdui->setMsg("Upgrade Repository: Drop Old Repository done"); + mdui->setEndStep(TRUE); + mdui->setSubstep(0); + + return 0; + } + break; + + default: + return -1; + } + } // while + + return 0; +} + +short CmpSeabaseDDL::upgradeReposUndo(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo *mdui) +{ + Lng32 cliRC = 0; + + while (1) // exit via return stmt in switch + { + switch (mdui->subStep()) + { + // error return codes from upgradeRepos can be mapped to + // the right recovery substep by this formula: substep = -(retcode + 1) + case 0: // corresponds to -1 return code from upgradeRepos (or + // to full recovery after some error after upgradeRepos) + case 1: // corresponds to -2 return code from upgradeRepos + case 2: // corresponds to -3 return code from upgradeRepos + { + mdui->setMsg("Upgrade Repository: Restoring Old Repository"); + mdui->setSubstep(2*mdui->subStep()+3); // go to appropriate case + mdui->setEndStep(FALSE); + + return 0; + } + break; + + case 3: + { + mdui->setMsg(" Start: Drop New Repository"); mdui->subStep()++; mdui->setEndStep(FALSE); - + return 0; } break; - case 11: + case 4: { - mdui->setMsg("Upgrade Repository: done"); + // drop new repository; ignore errors + dropRepos(cliInterface, FALSE/*new repos*/, FALSE/*no schema drop*/, + TRUE /* don't drop new tables that haven't been upgraded */); + cliInterface->clearGlobalDiags(); + mdui->setMsg(" End: Drop New Repository"); mdui->subStep()++; - mdui->setEndStep(TRUE); - mdui->setSubstep(0); - + mdui->setEndStep(FALSE); + + return 0; + } + break; + + case 5: + { + mdui->setMsg(" Start: Rename Old Repository back to New"); + mdui->subStep()++; + mdui->setEndStep(FALSE); + return 0; } break; - case 12: // label_error1 + case 6: { - // rename old repos to current + // rename old repos to current; ignore errors alterRenameRepos(cliInterface, FALSE); - return -1; + cliInterface->clearGlobalDiags(); + mdui->setMsg(" End: Rename Old Repository back to New"); + mdui->subStep()++; + mdui->setEndStep(FALSE); + + return 0; } break; - case 13: // label_error2 + case 7: { - // drop new repository - dropRepos(cliInterface, FALSE/*new repos*/, FALSE/*no schema drop*/); - - // rename old to new - alterRenameRepos(cliInterface, FALSE); + mdui->setMsg("Upgrade Repository: Restore done"); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); - return -1; + return 0; } break; http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/1cfc0ed8/core/sql/sqlcomp/CmpSeabaseDDLupgrade.cpp ---------------------------------------------------------------------- diff --git a/core/sql/sqlcomp/CmpSeabaseDDLupgrade.cpp b/core/sql/sqlcomp/CmpSeabaseDDLupgrade.cpp index 1c058df..48ad516 100644 --- a/core/sql/sqlcomp/CmpSeabaseDDLupgrade.cpp +++ b/core/sql/sqlcomp/CmpSeabaseDDLupgrade.cpp @@ -310,15 +310,22 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, char msgBuf[1000]; char buf[10000]; + // interfaces for upgrading subsystems; OK to create on stack for + // now as they are stateless + CmpSeabaseUpgradeRepository upgradeRepository; + CmpSeabaseUpgradePrivMgr upgradePrivMgr; + ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, CmpCommon::context()->sqlSession()->getParentQid()); ExpHbaseInterface * ehi = NULL; while (1) { - // TODO: remove this debugging code - cout << "mdui->step() is " << mdui->step() << ", mdui->subStep() is " << mdui->subStep() << endl; - // TODO: remove the above debugging code + // The line below is useful when debugging upgrade; it shows the step progression + // through the upgrade state machine. + // cout << "mdui->step() is " << mdui->step() + // << ", mdui->subStep() is " << mdui->subStep() << endl; + switch (mdui->step()) { case UPGRADE_START: @@ -440,7 +447,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, case 2: { - str_sprintf(msgBuf, " Metadata need to be upgraded or reinitialized."); + str_sprintf(msgBuf, " Metadata needs to be upgraded or reinitialized."); mdui->setMsg(msgBuf); mdui->setEndStep(FALSE); @@ -534,7 +541,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, else { if (retcode == -1395) - str_sprintf(msgBuf, " Metadata need to be upgraded or reinitialized (Current Version %Ld.%Ld.%Ld, Expected Version %Ld.%Ld.%Ld).", + str_sprintf(msgBuf, " Metadata needs to be upgraded or reinitialized (Current Version %Ld.%Ld.%Ld, Expected Version %Ld.%Ld.%Ld).", mdCurrMajorVersion, mdCurrMinorVersion, mdCurrUpdateVersion, (Int64)METADATA_MAJOR_VERSION, (Int64)METADATA_MINOR_VERSION, (Int64)METADATA_UPDATE_VERSION); else @@ -577,7 +584,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, case 2: { - str_sprintf(msgBuf, " Metadata need to be updated with current software version. Run 'initialize trafodion, update software version' to update it."); + str_sprintf(msgBuf, " Metadata needs to be updated with current software version. Run 'initialize trafodion, update software version' to update it."); mdui->setMsg(msgBuf); mdui->setEndStep(FALSE); @@ -666,17 +673,17 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, if (isMDUpgradeNeeded()) { - upgItems += " Catalogs, "; + upgItems += " Catalogs,"; } if (isViewsUpgradeNeeded()) { upgItems += " Views,"; } - if (isPrivsUpgradeNeeded()) + if (upgradePrivMgr.needsUpgrade(this)) { upgItems += " Privileges,"; } - if (isReposUpgradeNeeded()) + if (upgradeRepository.needsUpgrade(this)) { upgItems += " Repository,"; } @@ -686,7 +693,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, upgItems += "."; } } - str_sprintf(msgBuf, " Metadata need to be upgraded from Version %Ld.%Ld.%Ld to %Ld.%Ld.%Ld.%s", + str_sprintf(msgBuf, " Metadata needs to be upgraded from Version %Ld.%Ld.%Ld to %Ld.%Ld.%Ld.%s", mdCurrMajorVersion, mdCurrMinorVersion/10, (mdCurrMinorVersion - (mdCurrMinorVersion/10)*10), METADATA_MAJOR_VERSION, METADATA_MINOR_VERSION, @@ -1426,7 +1433,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { if (NOT isViewsUpgradeNeeded()) { - mdui->setStep(UPGRADE_PRIV_MGR); + mdui->setStep(UPGRADE_REPOS); mdui->setSubstep(0); break; } @@ -1492,7 +1499,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, } mdui->setMsg("Update Metadata Views: done"); - mdui->setStep(UPGRADE_PRIV_MGR); + mdui->setStep(UPGRADE_REPOS); mdui->setSubstep(0); mdui->setEndStep(TRUE); @@ -1506,13 +1513,20 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, case UPGRADE_PRIV_MGR: { + // Note: We used to do this case before UPGRADE_REPOS, but + // that was changed in Trafodion 2.1 to do it afterwards instead. + // The reason is that the Privilege Manager does not adhere + // to the CmpSeabaseUpgradeSubsystem class contract; its drop + // and recovery logic is packaged in its upgrade method. So, + // we have to do the Privilege Manager upgrade last since there + // is no way to undo it if we have an error afterward. switch (mdui->subStep()) { case 0: { - if (NOT isPrivsUpgradeNeeded()) + if (NOT upgradePrivMgr.needsUpgrade(this)) { - mdui->setStep(UPGRADE_REPOS); + mdui->setStep(UPDATE_VERSION); mdui->setSubstep(0); break; } @@ -1527,12 +1541,11 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, case 1: { - NAString privMgrDoneMsg; if (xnInProgress(&cliInterface)) { *CmpCommon::diags() << DgSqlCode(-20123); - mdui->setStep(UPGRADE_FAILED); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; @@ -1543,16 +1556,16 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); - mdui->setStep(UPGRADE_FAILED); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; } - cliRC = upgradePrivMgr(&cliInterface, ddlXns, privMgrDoneMsg); + cliRC = upgradePrivMgr.doUpgrade(&cliInterface,mdui,this,ddlXns); if (cliRC != 0) { - mdui->setStep(UPGRADE_FAILED); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; @@ -1563,14 +1576,14 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); - mdui->setStep(UPGRADE_FAILED); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; } - mdui->setMsg(privMgrDoneMsg.data()); - mdui->setStep(UPGRADE_REPOS); + // mdui->setMsg() was called in upgradePrivMgr.doUpgrade() + mdui->setStep(UPDATE_VERSION); mdui->setSubstep(0); mdui->setEndStep(TRUE); @@ -1586,7 +1599,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { if (NOT isReposUpgradeNeeded()) { - mdui->setStep(UPDATE_VERSION); + mdui->setStep(UPGRADE_PRIV_MGR); mdui->setSubstep(0); break; } @@ -1601,18 +1614,18 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, break; } - cliRC = upgradeRepos(&cliInterface, mdui); + cliRC = upgradeRepository.doUpgrade(&cliInterface, mdui, this, ddlXns); if (cliRC != 0) { - mdui->setStep(UPGRADE_FAILED); - mdui->setSubstep(0); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); + mdui->setSubstep(-(cliRC+1)); break; } if (mdui->endStep()) { - mdui->setStep(UPDATE_VERSION); + mdui->setStep(UPGRADE_PRIV_MGR); mdui->setSubstep(0); } @@ -1640,7 +1653,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { *CmpCommon::diags() << DgSqlCode(-20123); - mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_MD); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; @@ -1651,7 +1664,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); - mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_MD); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; @@ -1660,7 +1673,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, cliRC = updateSeabaseVersions(&cliInterface, TRAFODION_SYSCAT_LIT); if (cliRC < 0) { - mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_MD); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; @@ -1674,7 +1687,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); - mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_MD); + mdui->setStep(UPGRADE_FAILED_RESTORE_OLD_REPOS); mdui->setSubstep(0); break; @@ -1686,7 +1699,7 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, (NOT isViewsUpgradeNeeded())) mdui->setStep(METADATA_UPGRADED); else - mdui->setStep(OLD_MD_TABLES_HBASE_DELETE); + mdui->setStep(OLD_REPOS_DROP); mdui->setSubstep(0); mdui->setEndStep(TRUE); @@ -1697,6 +1710,32 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, } break; + case OLD_REPOS_DROP: + { + if (upgradeRepository.needsUpgrade(this)) + { + if (upgradeRepository.doDrops(&cliInterface,mdui,this)) + { + // no status message in this case so no return + cliInterface.clearGlobalDiags(); + mdui->setStep(OLD_MD_TABLES_HBASE_DELETE); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); + } + else + { + if (mdui->endStep()) + { + mdui->setStep(OLD_MD_TABLES_HBASE_DELETE); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); + } + return 0; + } + } + } + break; + case OLD_MD_TABLES_HBASE_DELETE: { switch (mdui->subStep()) @@ -1814,6 +1853,51 @@ short CmpSeabaseMDupgrade::executeSeabaseMDupgrade(CmpDDLwithStatusInfo *mdui, } break; + case UPGRADE_FAILED_RESTORE_OLD_REPOS: + { + // Note: We can't combine this case with UPGRADE_FAILED etc. + // below, because the subsystem code uses mdui->subStep() + // to keep track of its progress. + + if (upgradeRepository.needsUpgrade(this)) + { + if (xnInProgress(&cliInterface)) + { + cliRC = rollbackXn(&cliInterface); + if (cliRC < 0) + { + // ignore errors + } + } + + if (upgradeRepository.doUndo(&cliInterface,mdui,this)) + { + // ignore errors; no status message so just continue on + cliInterface.clearGlobalDiags(); + mdui->setStep(UPGRADE_FAILED_DROP_OLD_MD); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); + } + else + { + if (mdui->endStep()) + { + mdui->setStep(UPGRADE_FAILED_DROP_OLD_MD); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); + } + return 0; + } + } + else + { + mdui->setStep(UPGRADE_FAILED_DROP_OLD_MD); + mdui->setSubstep(0); + mdui->setEndStep(TRUE); + } + } + break; + case UPGRADE_FAILED: case UPGRADE_FAILED_RESTORE_OLD_MD: case UPGRADE_FAILED_DROP_OLD_MD: @@ -2414,6 +2498,83 @@ short CmpSeabaseMDupgrade::customizeNewMDv23tov30(CmpDDLwithStatusInfo *mdui, } // ---------------------------------------------------------------------------- +// Methods for class CmpSeabaseUpgradeRepository +// ---------------------------------------------------------------------------- +NABoolean CmpSeabaseUpgradeRepository::needsUpgrade(CmpSeabaseMDupgrade * ddlState) +{ + return ddlState->isReposUpgradeNeeded(); +} + +short CmpSeabaseUpgradeRepository::doUpgrade(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState, + NABoolean /* ddlXns */) +{ + return ddlState->upgradeRepos(cliInterface,mdui); +} + +short CmpSeabaseUpgradeRepository::doDrops(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, CmpSeabaseMDupgrade * ddlState) +{ + return ddlState->upgradeReposComplete(cliInterface,mdui); +} + +short CmpSeabaseUpgradeRepository::doUndo(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, CmpSeabaseMDupgrade * ddlState) +{ + return ddlState->upgradeReposUndo(cliInterface,mdui); +} + +// ---------------------------------------------------------------------------- +// Methods for class CmpSeabaseUpgradePrivMgr +// ---------------------------------------------------------------------------- +NABoolean CmpSeabaseUpgradePrivMgr::needsUpgrade(CmpSeabaseMDupgrade * ddlState) +{ + return ddlState->isPrivsUpgradeNeeded(); +} + +short CmpSeabaseUpgradePrivMgr::doUpgrade(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState, + NABoolean ddlXns) +{ + // If this is refactored in the future to return multiple messages + // then mdui will need to be passed in, and setEndStep called when + // we want to stop redriving this method. + NAString doneString; + short retcode = ddlState->upgradePrivMgr(cliInterface, ddlXns, doneString); + if (!retcode) + { + mdui->setMsg(doneString.data()); + mdui->setEndStep(TRUE); + } + return retcode; +} + +short CmpSeabaseUpgradePrivMgr::doDrops(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, CmpSeabaseMDupgrade * ddlState) +{ + // At the moment, the privilege manager does not adhere to the contract. + // It does its drops inside the CmpSeabaseMDupgrade::upgradePrivMgr + // method. That is why the upgrade state machine above must do the + // privilege manager last. Because if there were an error afterward + // that required us to revert to previous state, we couldn't since + // the drops have already been done. + return 0; // stubbed, until Privilege Manager upgrade is refactored +} + +short CmpSeabaseUpgradePrivMgr::doUndo(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, CmpSeabaseMDupgrade * ddlState) +{ + // At the moment, the privilege manager does not adhere to the contract. + // It does its recovery inside the CmpSeabaseMDupgrade::upgradePrivMgr + // method. That is why the upgrade state machine above must do the + // privilege manager last. Because if there were an error afterward + // that required us to revert to previous state, we couldn't since + // the drops have already been done. + return 0; // stubbed, until Privilege Manager upgrade is refactored +} +// ---------------------------------------------------------------------------- // method: upgradePrivMgr // // This method upgrades the privilege manager repository http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/1cfc0ed8/core/sql/sqlcomp/CmpSeabaseDDLupgrade.h ---------------------------------------------------------------------- diff --git a/core/sql/sqlcomp/CmpSeabaseDDLupgrade.h b/core/sql/sqlcomp/CmpSeabaseDDLupgrade.h index 3fcc94b..4182a3d 100644 --- a/core/sql/sqlcomp/CmpSeabaseDDLupgrade.h +++ b/core/sql/sqlcomp/CmpSeabaseDDLupgrade.h @@ -60,6 +60,81 @@ CmpSeabaseDDLupgrade.cpp -- modify CUSTOMIZE_NEW_MD case if something specified need to be done. Ex: update new sql_data_type field in COLUMNS table +Similar changes may be needed for subsystems that are upgraded as part +of "initialize trafodion, upgrade", for example the Repository and the +Privilege Manager. The Repository upgrade code is in CmpSeabaseDDLrepos.h/.cpp, +while the Privilege Manager code is in the Priv* modules. + +The architecture of upgrade is as follows: + +Guiding principle: + +In the event of a failure, we do our best to put things back to their +initial state. That allows the user to try again (for example, for a +transient HBase difficulty), or to reinstall the old software if desired. + +Control flow: + +First we upgrade the metadata tables ("_MD_" schema). This has to be done +using bootstrapping techniques. We rename the existing metadata tables +to an old name, using HBase primitives. We then create the new metadata +tables, and copy the data from the old tables to the new, transforming it +as needed. The copy is done using a vanilla UPSERT/SELECT. We can do this +because at process startup time, the NATable cache is bootstrapped with +both the old and new metadata table definitions. We don't drop the old +metadata tables yet, because we want to be able to revert to our initial +state should an error occur. + +Subsystems are upgraded after the metadata table upgrade succeeds. The +subsystems are not self-referencing from a metadata point of view. So, +for example, it is possible to rename a subsystem table using a SQL +ALTER TABLE RENAME statement, which is not true for a metadata table. + +Subsystems go through basically the same steps: Rename the existing table +to old, create the new, copy the data in. Again, the old tables are not +dropped yet, so we can revert in the event of an error (in the next +subsystem for example). + +Once all the subsystems have been upgraded, we update the version in +the VERSIONS table. + +Finally, we drop all the old tables. We can ignore errors at this point +because we have good new tables. + +If there is an error, we undo the upgrade for each subsystem, then undo +the upgrade for the metadata tables. Again, we can use vanilla SQL for +the subsystems, but must use low level HBase primitives for the metadata +tables. + +The CmpSeabaseUpgradeSubsystem class defines the contract that a subsystem +must implement in order to be called from "initialize trafodion, upgrade". +Briefly, each subsystem must implement the following: + +-- a method that says whether an upgrade is needed for that subsystem +-- a method that does the upgrade, but leaves the old tables around + so that they can be recovered in case we have to undo the upgrade +-- a method that drops the old tables, called when we have decided that + the upgrade has succeeded +-- a method that undoes the upgrade, called when an error is detected + in "initialize trafodion, upgrade". + +These are packaged in separate methods because, as mentioned above, +processing is interleaved. We do all the subsystem upgrades. If they are +all successful, we do the drops. But if there was an error, we do the undo's. + +Data flow: + +The "initialize trafodion, upgrade" statement is a DDL statement that returns +rows. The rows are status messages, which if displayed immediately (as they +would be, say, in sqlci or trafci), give a real time status of the operation. + +As such, the upgrade methods are redriven after each row is returned. The +upgrade processing occurs in a tdm_arkcmp process. All state is kept in the +message objects communicated between it and its invoker. For this reason, +the classes used for the upgrade methods are stateless. Instead, state +consists of state-machine step information which is stored in a +CmpDDLwithStatusInfo object. + ***************************************************************************************/ // structure containing information on old and new MD tables @@ -501,13 +576,14 @@ class CmpSeabaseMDupgrade : public CmpSeabaseDDL OLD_TABLES_MD_DELETE, OLD_MD_TABLES_HBASE_DELETE, UPDATE_MD_VIEWS, - UPGRADE_PRIV_MGR, UPGRADE_REPOS, + UPGRADE_PRIV_MGR, UPDATE_VERSION, - OLD_MD_DROP_POST, + OLD_REPOS_DROP, METADATA_UPGRADED, UPGRADE_DONE, UPGRADE_FAILED, + UPGRADE_FAILED_RESTORE_OLD_REPOS, UPGRADE_FAILED_RESTORE_OLD_MD, UPGRADE_FAILED_DROP_OLD_MD, GET_MD_VERSION, @@ -553,5 +629,118 @@ class CmpSeabaseMDupgrade : public CmpSeabaseDDL }; + +// abstract class defining the contract that a subsystem must implement +// in order to be called from "initialize trafodion, upgrade" +class CmpSeabaseUpgradeSubsystem +{ + public: + + CmpSeabaseUpgradeSubsystem(void) { } ; + ~CmpSeabaseUpgradeSubsystem(void) { } ; + + // Returns TRUE if an upgrade is needed, FALSE if not + virtual NABoolean needsUpgrade(CmpSeabaseMDupgrade * ddlState) = 0; + + // The next three methods have the same return interface: + // + // returns 0 if successful or not done yet, a negative value + // if not. ("Not done yet" means call again. This allows + // the method to return status text messages to the user as + // it progresses in its processing.) To signal successful + // completion, the method should return 0, and call + // mdui->setEndStep(TRUE). Any state needed across calls + // should be kept in the CmpDDLwithStatusInfo object, + // e.g., via its setStep and setSubstep methods. + // + // The negative value can be used to signal what sort of + // recovery is needed. + + // Does the upgrade, but leaves old tables there in case we + // need to undo. + virtual short doUpgrade(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState, + NABoolean ddlXns) = 0; + + // Drops the old tables left behind by doUpgrade; errors + // are typically ignored as at this point upgrade is + // done except for dropping old tables. + virtual short doDrops(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState) = 0; + + // Undoes the upgrade by putting the old tables back to + // their original names. + virtual short doUndo(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState) = 0; + + private: + + // for now, avoid having any state; the upgrade mainline + // keeps most of its state in the CmpDDLwithStatusInfo message +}; + +// Repository specialization + +class CmpSeabaseUpgradeRepository : public CmpSeabaseUpgradeSubsystem +{ + public: + + CmpSeabaseUpgradeRepository(void) { } ; + ~CmpSeabaseUpgradeRepository(void) { } ; + + NABoolean needsUpgrade(CmpSeabaseMDupgrade * ddlState); + + short doUpgrade(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState, + NABoolean ddlXns); + + short doDrops(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState); + + short doUndo(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState); + + private: + + // avoid having state for now + +}; + +// Privilege Manager specialization + +class CmpSeabaseUpgradePrivMgr : public CmpSeabaseUpgradeSubsystem +{ + public: + + CmpSeabaseUpgradePrivMgr(void) { } ; + ~CmpSeabaseUpgradePrivMgr(void) { } ; + + NABoolean needsUpgrade(CmpSeabaseMDupgrade * ddlState); + + short doUpgrade(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState, + NABoolean ddlXns); + + short doDrops(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState); + + short doUndo(ExeCliInterface * cliInterface, + CmpDDLwithStatusInfo * mdui, + CmpSeabaseMDupgrade * ddlState); + + private: + + // avoid having state for now + +}; + #endif
