You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafodion.apache.org by db...@apache.org on 2016/07/18 16:20:38 UTC

[13/16] incubator-trafodion git commit: Refactor and fix repository upgrade code

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 <db...@apache.org>
Authored: Wed Jul 13 18:42:53 2016 +0000
Committer: Dave Birdsall <db...@apache.org>
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