From a1c05a12054b831b0aead0bd5eac9c6bdac6a655 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Tue, 17 Nov 2015 17:27:16 +0000
Subject: [PATCH] OPENDJ-2364 PR-148 Change backend type during upgrade

---
 opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java |  103 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 90 insertions(+), 13 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java
index 6046aef..1f0b881 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java
@@ -420,27 +420,26 @@
    *          The group of tasks to invoke if the user agrees.
    * @return An upgrade task which will only be invoked if the user confirms agreement.
    */
-  public static UpgradeTask requireConfirmation(final LocalizableMessage message, final UpgradeTask... tasks)
+  static UpgradeTask requireConfirmation(
+          final LocalizableMessage message, final int defaultResponse, final UpgradeTask... tasks)
   {
     return conditionalUpgradeTasks(new UpgradeCondition()
     {
       @Override
       public boolean shouldPerformUpgradeTasks(final UpgradeContext context) throws ClientException
       {
-        return context.confirmYN(INFO_UPGRADE_TASK_NEEDS_USER_CONFIRM.get(message), YES) == YES;
+        return context.confirmYN(INFO_UPGRADE_TASK_NEEDS_USER_CONFIRM.get(message), defaultResponse) == YES;
       }
     }, tasks);
   }
 
-  /**
-   * Determines whether conditional tasks should be performed.
-   */
-  private static interface UpgradeCondition
+  /** Determines whether conditional tasks should be performed. */
+  interface UpgradeCondition
   {
     boolean shouldPerformUpgradeTasks(final UpgradeContext context) throws ClientException;
   }
 
-  private static UpgradeTask conditionalUpgradeTasks(final UpgradeCondition condition, final UpgradeTask... tasks)
+  static UpgradeTask conditionalUpgradeTasks(final UpgradeCondition condition, final UpgradeTask... tasks)
   {
     return new AbstractUpgradeTask()
     {
@@ -937,12 +936,7 @@
       }
 
       private boolean isJeLibraryAvailable() {
-        try {
-          Class.forName("com.sleepycat.je.Environment");
-          return true;
-        } catch (Exception e) {
-          return false;
-        }
+        return isClassAvailable("com.sleepycat.je.Environment");
       }
 
       private String newName(final DN baseDN) {
@@ -962,6 +956,89 @@
     };
   }
 
+  /**
+   * Creates backups of the local DB backends directories by renaming adding them a ".bak" suffix.
+   *  e.g "userRoot" would become "userRoot.bak"
+   */
+  static UpgradeTask renameLocalDBBackendDirectories()
+  {
+    return new AbstractUpgradeTask()
+    {
+      private boolean reimportRequired = false;
+
+      @Override
+      public void perform(UpgradeContext context) throws ClientException
+      {
+        try
+        {
+          Filter filter = Filter.equality("objectclass", "ds-cfg-local-db-backend");
+          SearchRequest findLocalDBBackends = Requests.newSearchRequest(DN.rootDN(), SearchScope.WHOLE_SUBTREE, filter);
+          try (final EntryReader jeBackends = searchConfigFile(findLocalDBBackends))
+          {
+            while (jeBackends.hasNext())
+            {
+              Upgrade.setHasPostUpgradeTask(true);
+              reimportRequired = true;
+
+              Entry jeBackend = jeBackends.readEntry();
+              File dbParent = UpgradeUtils.getFileForPath(jeBackend.parseAttribute("ds-cfg-db-directory").asString());
+              String id = jeBackend.parseAttribute("ds-cfg-backend-id").asString();
+
+              // Use canonical paths so that the progress message is more readable.
+              File dbDirectory = new File(dbParent, id).getCanonicalFile();
+              File dbDirectoryBackup = new File(dbParent, id + ".bak").getCanonicalFile();
+              if (dbDirectory.exists() && !dbDirectoryBackup.exists())
+              {
+                LocalizableMessage msg = INFO_UPGRADE_TASK_RENAME_JE_DB_DIR.get(dbDirectory, dbDirectoryBackup);
+                ProgressNotificationCallback pnc = new ProgressNotificationCallback(0, msg, 0);
+                context.notifyProgress(pnc);
+                boolean renameSucceeded = dbDirectory.renameTo(dbDirectoryBackup);
+                context.notifyProgress(pnc.setProgress(renameSucceeded ? 100 : -1));
+              }
+            }
+          }
+        }
+        catch (Exception e)
+        {
+          logger.error(LocalizableMessage.raw(e.getMessage()));
+        }
+      }
+
+      @Override
+      public void postUpgrade(UpgradeContext context) throws ClientException
+      {
+        postponePostUpgrade(context);
+      }
+
+      @Override
+      public void postponePostUpgrade(UpgradeContext context) throws ClientException
+      {
+        if (reimportRequired)
+        {
+          context.notify(INFO_UPGRADE_TASK_RENAME_JE_DB_DIR_WARNING.get(), TextOutputCallback.WARNING);
+        }
+      }
+    };
+  }
+
+  static boolean isOEMVersion()
+  {
+    return !isClassAvailable("org.opends.server.backends.jeb.JEBackend");
+  }
+
+  private static boolean isClassAvailable(final String className)
+  {
+    try
+    {
+      Class.forName(className);
+      return true;
+    }
+    catch (Exception e)
+    {
+      return false;
+    }
+  }
+
   /** This inner classes causes JE to be lazily linked and prevents runtime errors if JE is not in the classpath. */
   static final class JEHelper {
     private static ClientException clientException(final File backendDirectory, final DatabaseException e) {

--
Gitblit v1.10.0