From 75a571bfa9d382b75e664eba3dfd58d17c694e11 Mon Sep 17 00:00:00 2001
From: Violette Roche-Montane <violette.roche-montane@forgerock.com>
Date: Tue, 03 Sep 2013 09:27:02 +0000
Subject: [PATCH] CR-2181 OPENDJ-1030 Upgrade : add a task to rebuild ds-sync-hist index when upgrading from 2.5.0-Xpress
---
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTask.java | 39 ++-
opendj-sdk/opends/src/messages/messages/tools.properties | 16 +
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/AbstractUpgradeTask.java | 39 ++
opendj-sdk/opends/src/server/org/opends/server/tools/RebuildIndex.java | 185 +++++++++++++-
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/Upgrade.java | 127 +++++++---
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeCli.java | 10
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeLog.java | 26 ++
opendj-sdk/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java | 7
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java | 175 ++++++++++++--
opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java | 43 +--
10 files changed, 519 insertions(+), 148 deletions(-)
diff --git a/opendj-sdk/opends/src/messages/messages/tools.properties b/opendj-sdk/opends/src/messages/messages/tools.properties
index 1bad9ed..8e8c789 100644
--- a/opendj-sdk/opends/src/messages/messages/tools.properties
+++ b/opendj-sdk/opends/src/messages/messages/tools.properties
@@ -2537,6 +2537,16 @@
(if present)
SEVERE_ERR_UPGRADE_RENAME_SNMP_SECURITY_CONFIG_FILE_1838=An error occurred when \
trying to rename the SNMP security config file: %s
+INFO_UPGRADE_REBUILD_INDEX_STARTS_1839=Rebuilding index(es) %s
+INFO_UPGRADE_REBUILD_INDEX_ENDS_1840=Rebuild index task ends
+INFO_UPGRADE_PERFORMING_POST_TASKS_1841=Performing post upgrade tasks
+INFO_UPGRADE_POST_TASKS_COMPLETE_1842=Post upgrade tasks complete
+SEVERE_ERR_UPGRADE_PERFORMING_POST_TASKS_FAIL_1843=An error occured during post \
+upgrade task. Process aborted. Please check log for further details
+INFO_UPGRADE_REBUILD_INDEX_DECLINED_1844 =You have to rebuild the '%s' index \
+manually to get a fully functional server
+SEVERE_ERR_UPGRADE_INVALID_LOG_FILE_1845=Invalid log file %s
+INFO_UPGRADE_REBUILD_INDEX_ARGUMENTS_1846=The rebuild index tool arguments are %s
# Upgrade tasks
INFO_UPGRADE_TASK_6869_SUMMARY_10000=Fixing de-DE collation matching rule OID
@@ -2561,7 +2571,5 @@
INFO_UPGRADE_TASK_8985_1_SUMMARY_10017=Adding 'emailAddress' attribute
INFO_UPGRADE_TASK_8985_2_SUMMARY_10018=Updating subject attribute to user attribute configuration
INFO_UPGRADE_TASK_9013_DESCRIPTION_10019=OpenDJ 2.5.0-Xpress1 introduced a \
- regression in the ds-sync-hist ordering index. This index must be rebuilt \
- after the upgrade has completed and before restarting OpenDJ. Do you wish to \
- continue?
-
+ regression in the ds-sync-hist ordering index. This index has to be rebuilt and this could take a long time \
+ to proceed. Do you want to launch this process at automatically at the end of the upgrade ?
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/RebuildIndex.java b/opendj-sdk/opends/src/server/org/opends/server/tools/RebuildIndex.java
index 1c4ef96..1cf7ab7 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/RebuildIndex.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/RebuildIndex.java
@@ -36,6 +36,7 @@
import static org.opends.server.util.StaticUtils.*;
import org.opends.server.util.BuildVersion;
+import org.opends.server.util.StaticUtils;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.LDAPConnectionArgumentParser;
@@ -91,6 +92,11 @@
"org.opends.server.tools.RebuildIndex",
INFO_REBUILDINDEX_TOOL_DESCRIPTION.get());
+ private RebuildConfig rebuildConfig = new RebuildConfig();
+ private Backend currentBackend = null;
+
+
+
/**
* Processes the command-line arguments and invokes the rebuild process.
*
@@ -329,38 +335,52 @@
setErrorAndDebugLogPublisher(out, err);
}
+ if (!configureRebuildProcess(baseDNString.getValue()))
+ {
+ return 1;
+ }
+
+ return rebuildIndex(currentBackend, rebuildConfig);
+ }
+
+ /**
+ * Configures the rebuild index process. i.e.: decodes the selected DN and
+ * retrieves the backend which holds it. Finally, initializes and sets the
+ * rebuild configuration.
+ *
+ * @param dn
+ * User selected base DN.
+ * @return A boolean representing the result of the process.
+ */
+ private boolean configureRebuildProcess(final String dn) {
// Decodes the base DN provided by the user.
DN rebuildBaseDN = null;
try
{
- rebuildBaseDN = DN.decode(baseDNString.getValue());
+ rebuildBaseDN = DN.decode(dn);
}
catch (Exception e)
{
final Message message =
- ERR_CANNOT_DECODE_BASE_DN.get(baseDNString.getValue(),
+ ERR_CANNOT_DECODE_BASE_DN.get(dn,
getExceptionMessage(e));
logError(message);
- return 1;
+ return false;
}
// Retrieves the backend which holds the selected base DN.
- Backend backend = null;
try
{
- backend = retrieveBackend(rebuildBaseDN);
+ setCurrentBackend(retrieveBackend(rebuildBaseDN));
}
catch (Exception e)
{
logError(Message.raw(e.getMessage()));
- return 1;
+ return false;
}
- // Sets the rebuild index configuration.
- final RebuildConfig rebuildConfig =
- initializeRebuildIndexConfiguration(rebuildBaseDN);
-
- return rebuildIndex(backend, rebuildConfig);
+ setRebuildConfig(initializeRebuildIndexConfiguration(rebuildBaseDN));
+ return true;
}
/**
@@ -396,6 +416,7 @@
/**
* Initializes the directory server.<br />
+ * Processes to :
* - bootstrapClient
* - initializeJMX
* - initializeConfiguration
@@ -405,10 +426,10 @@
*
* @param directoryServer
* The current instance.
- * @param outStream
+ * @param out
* The output stream to use for standard output, or {@code null} if
* standard output is not needed.
- * @param errStream
+ * @param err
* The output stream to use for standard error, or {@code null} if
* standard error is not needed.
* @return The error code.
@@ -527,32 +548,32 @@
private RebuildConfig initializeRebuildIndexConfiguration(
final DN rebuildBaseDN)
{
- final RebuildConfig rebuildConfig = new RebuildConfig();
- rebuildConfig.setBaseDN(rebuildBaseDN);
+ final RebuildConfig config = new RebuildConfig();
+ config.setBaseDN(rebuildBaseDN);
for (final String s : indexList.getValues())
{
- rebuildConfig.addRebuildIndex(s);
+ config.addRebuildIndex(s);
}
if (rebuildAll.isPresent())
{
- rebuildConfig.setRebuildMode(RebuildMode.ALL);
+ config.setRebuildMode(RebuildMode.ALL);
}
else if (rebuildDegraded.isPresent())
{
- rebuildConfig.setRebuildMode(RebuildMode.DEGRADED);
+ config.setRebuildMode(RebuildMode.DEGRADED);
}
else
{
if (clearDegradedState.isPresent())
{
- rebuildConfig.isClearDegradedState(true);
+ config.isClearDegradedState(true);
}
- rebuildConfig.setRebuildMode(RebuildMode.USER_DEFINED);
+ config.setRebuildMode(RebuildMode.USER_DEFINED);
}
- rebuildConfig.setTmpDirectory(tmpDirectory.getValue());
- return rebuildConfig;
+ config.setTmpDirectory(tmpDirectory.getValue());
+ return config;
}
/**
@@ -635,7 +656,7 @@
/**
* Gets information about the backends defined in the server. Iterates through
- * them, finding the one backend to be verified.
+ * them, finding the one that holds the base DN.
*
* @param selectedDN
* The user selected DN.
@@ -699,6 +720,82 @@
}
/**
+ * This function allow internal use of the rebuild index tools. This function
+ * rebuilds indexes shared by multiple backends.
+ *
+ * @param initializeServer
+ * Indicates whether to initialize the server.
+ * @param out
+ * The print stream which is used to display errors/debug lines.
+ * Usually redirected into a logger if the tool is used as external.
+ * @param args
+ * The arguments used to launch the rebuild index process.
+ * @return An integer indicating the result of this action.
+ */
+ public int rebuildIndexesWithinMultipleBackends(
+ final boolean initializeServer, final PrintStream out,
+ final String... args)
+ {
+ try
+ {
+ setErrorAndDebugLogPublisher(out, out);
+
+ try
+ {
+ initializeArguments(true);
+ }
+ catch (ArgumentException ae)
+ {
+ final Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+ out.println(wrapText(message, MAX_LINE_WIDTH));
+ return 1;
+ }
+
+ try
+ {
+ argParser.parseArguments(args);
+ }
+ catch (ArgumentException ae)
+ {
+ final Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+ out.println(wrapText(message, MAX_LINE_WIDTH));
+ return 1;
+ }
+
+ final DirectoryServer directoryServer = DirectoryServer.getInstance();
+ if (initializeServer)
+ {
+ initializeServer(directoryServer, out, out);
+ }
+
+ for (final String dn : baseDNString.getValues())
+ {
+ if (!configureRebuildProcess(dn))
+ {
+ return 1;
+ }
+
+ final int result =
+ rebuildIndex(getCurrentBackend(), getRebuildConfig());
+ // If the rebuild index is going bad, process is stopped.
+ if (result != 0)
+ {
+ out.println(String.format(
+ "An error occurs during the rebuild index process" +
+ " in %s, rebuild index(es) aborted.",
+ dn));
+ return 1;
+ }
+ }
+ }
+ finally
+ {
+ StaticUtils.close(out);
+ }
+ return 0;
+ }
+
+ /**
* {@inheritDoc}
*/
public String getTaskId()
@@ -781,4 +878,46 @@
{
return RebuildTask.class;
}
+
+ /**
+ * Returns the rebuild configuration.
+ *
+ * @return The rebuild configuration.
+ */
+ public RebuildConfig getRebuildConfig()
+ {
+ return rebuildConfig;
+ }
+
+ /**
+ * Sets the rebuild configuration.
+ *
+ * @param rebuildConfig
+ * The rebuild configuration to set.
+ */
+ public void setRebuildConfig(RebuildConfig rebuildConfig)
+ {
+ this.rebuildConfig = rebuildConfig;
+ }
+
+ /**
+ * Returns the current backend.
+ *
+ * @return The current backend.
+ */
+ public Backend getCurrentBackend()
+ {
+ return currentBackend;
+ }
+
+ /**
+ * Sets the current backend.
+ *
+ * @param currentBackend
+ * The current backend to set.
+ */
+ public void setCurrentBackend(Backend currentBackend)
+ {
+ this.currentBackend = currentBackend;
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/AbstractUpgradeTask.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/AbstractUpgradeTask.java
index 59e9479..048a72c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/AbstractUpgradeTask.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/AbstractUpgradeTask.java
@@ -45,16 +45,6 @@
* {@inheritDoc}
*/
@Override
- public void end(UpgradeContext context)
- throws ClientException
- {
- // Nothing to do.
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public void interact(UpgradeContext context)
throws ClientException
{
@@ -75,9 +65,38 @@
* {@inheritDoc}
*/
@Override
+ public void perform(UpgradeContext context) throws ClientException
+ {
+ // Must be implemented.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void verify(UpgradeContext context)
throws ClientException
{
// Nothing to do.
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void postUpgrade(UpgradeContext context)
+ throws ClientException
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void postponePostUpgrade(UpgradeContext context)
+ throws ClientException
+ {
+ // Nothing to do.
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/Upgrade.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/Upgrade.java
index 0ebd39d..c946268 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/Upgrade.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/Upgrade.java
@@ -32,6 +32,7 @@
import static org.opends.messages.ToolMessages.*;
import static org.opends.server.tools.upgrade.FormattedNotificationCallback.*;
import static org.opends.server.tools.upgrade.UpgradeTasks.*;
+import static org.opends.server.tools.upgrade.LicenseFile.*;
import java.io.File;
import java.io.FileWriter;
@@ -89,6 +90,11 @@
static final int EXIT_CODE_MANUAL_INTERVENTION = 2;
/**
+ * If the upgrade contains some post upgrade tasks to do.
+ */
+ static boolean hasPostUpgradeTask = false;
+
+ /**
* Developers should register upgrade tasks below.
*/
private static final NavigableMap<BuildVersion, List<UpgradeTask>> TASKS =
@@ -292,7 +298,8 @@
/* See OPENDJ-992 */
register("2.5.0.9013",
regressionInVersion("2.5.0.7640",
- rebuildSingleIndex(INFO_UPGRADE_TASK_9013_DESCRIPTION.get())));
+ rebuildSingleIndex(INFO_UPGRADE_TASK_9013_DESCRIPTION.get(),
+ "ds-sync-hist")));
/*
* All upgrades will refresh the server configuration schema and generate
@@ -300,11 +307,8 @@
*/
registerLast(
copySchemaFile("02-config.ldif"),
- updateConfigUpgradeFolder());
-
- // TODO for tests.
- /*register("2.5.0.8657",
- rebuildAllIndexes(Message.raw("This is fake Rebuild Task")));*/
+ updateConfigUpgradeFolder(),
+ postUpgradeRebuildIndexes());
// @formatter:on
}
@@ -322,7 +326,7 @@
* @return A list containing all the tasks which are required in order to
* upgrade from {@code fromVersion} to {@code toVersion}.
*/
- private static List<UpgradeTask> getUpgradeTasks(
+ private static List<UpgradeTask> getUpgradeTasks(
final BuildVersion fromVersion, final BuildVersion toVersion)
{
final List<UpgradeTask> tasks = new LinkedList<UpgradeTask>();
@@ -347,12 +351,10 @@
public static void upgrade(final UpgradeContext context)
throws ClientException
{
-
-
- // Checks and validate the version number.
+ // Checks and validates the version number.
isVersionCanBeUpdated(context);
- // Server offline ?
+ // Server must be offline.
checkIfServerIsRunning();
context.notify( INFO_UPGRADE_TITLE.get(), TITLE_CALLBACK);
@@ -378,7 +380,7 @@
/*
* Verify tasks requirements.
- * Eg. if a task requires mandatory user interaction, like rebuild index,
+ * E.g. if a task requires mandatory user interaction
* and the application is non-interactive then, the process
* may abort immediately.
*/
@@ -407,21 +409,49 @@
context.notify(INFO_UPGRADE_PERFORMING_TASKS.get(),
TITLE_CALLBACK);
- perform(context, tasks);
+ /*
+ * Notify each task that the upgrade is about to be started.
+ */
+ for (final UpgradeTask task : tasks)
+ {
+ task.start(context);
+ }
+
+ /*
+ * Perform each task.
+ */
+ for (final UpgradeTask task : tasks)
+ {
+ task.perform(context);
+ }
+
if (UpgradeTasks.countErrors == 0)
{
- // At the end, and if only if succeed, we need to change the buildInfo
- // file with the version number updated.
+ /*
+ * The end of a successful upgrade is marked up with the build info
+ * file update and the license, if present, requires the creation of
+ * an approval file.
+ */
changeBuildInfoVersion(context);
- // Writes the license if needed.
- LicenseFile.createFileLicenseApproved();
+ createFileLicenseApproved();
}
else
{
context.notify(
ERR_UPGRADE_FAILS.get(UpgradeTasks.countErrors), TITLE_CALLBACK);
}
+
+ /*
+ * Performs the post upgrade tasks.
+ */
+ if (hasPostUpgradeTask && (UpgradeTasks.countErrors == 0))
+ {
+ context
+ .notify(INFO_UPGRADE_PERFORMING_POST_TASKS.get(), TITLE_CALLBACK);
+ performPostUpgradeTasks(context, tasks);
+ context.notify(INFO_UPGRADE_POST_TASKS_COMPLETE.get(), TITLE_CALLBACK);
+ }
}
catch (final ClientException e)
{
@@ -443,35 +473,29 @@
}
}
-
-
- private static void perform(final UpgradeContext context,
+ private static void performPostUpgradeTasks(final UpgradeContext context,
final List<UpgradeTask> tasks)
throws ClientException
{
- /*
- * Notify each task that the upgrade is about to be started.
- */
+ boolean isOk = true;
for (final UpgradeTask task : tasks)
{
- task.start(context);
- }
-
- /*
- * Perform each task.
- */
- for (final UpgradeTask task : tasks)
- {
- task.perform(context);
- }
-
- /*
- * Notify each task that the upgrade has completed. Tasks may do cleanup
- * work here, such as removing files.
- */
- for (final UpgradeTask task : tasks)
- {
- task.end(context);
+ if (isOk)
+ {
+ try
+ {
+ task.postUpgrade(context);
+ }
+ catch (ClientException e)
+ {
+ LOG.log(Level.SEVERE, e.getMessage());
+ isOk = false;
+ }
+ }
+ else
+ {
+ task.postponePostUpgrade(context);
+ }
}
}
@@ -673,6 +697,27 @@
}
}
+ /**
+ * Returns {@code true} if the current upgrade contains post upgrade tasks.
+ *
+ * @return {@code true} if the current upgrade contains post upgrade tasks.
+ */
+ static boolean hasPostUpgradeTask()
+ {
+ return hasPostUpgradeTask;
+ }
+
+ /**
+ * Sets {@code true} if the current upgrade contains post upgrade tasks.
+ *
+ * @param hasPostUpgradeTask
+ * {@code true} if the current upgrade contains post upgrade tasks.
+ */
+ static void setHasPostUpgradeTask(boolean hasPostUpgradeTask)
+ {
+ Upgrade.hasPostUpgradeTask = hasPostUpgradeTask;
+ }
+
// Prevent instantiation.
private Upgrade()
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeCli.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeCli.java
index da69d34..2dd0f9c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeCli.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeCli.java
@@ -41,6 +41,7 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.callback.Callback;
@@ -405,25 +406,32 @@
// Displays formatted notifications.
final FormattedNotificationCallback fnc =
(FormattedNotificationCallback) c;
- LOG.log(INFO, fnc.getMessage());
switch (fnc.getMessageSubType())
{
case TITLE_CALLBACK:
println(Style.TITLE, Message.raw(fnc.getMessage()), 0);
+ LOG.log(INFO, fnc.getMessage());
break;
case SUBTITLE_CALLBACK:
println(Style.SUBTITLE, Message.raw(fnc.getMessage()),
4);
+ LOG.log(INFO, fnc.getMessage());
break;
case NOTICE_CALLBACK:
println(Style.NOTICE, Message.raw(fnc.getMessage()), 1);
+ LOG.log(INFO, fnc.getMessage());
break;
case ERROR_CALLBACK:
println(Style.ERROR, Message.raw(fnc.getMessage()), 1);
+ LOG.log(Level.SEVERE, fnc.getMessage());
break;
case BREAKLINE:
println(Style.BREAKLINE, Message.raw(fnc.getMessage()), 1);
break;
+ case WARNING:
+ println(Style.WARNING, Message.raw(fnc.getMessage()), 2);
+ LOG.log(Level.WARNING, fnc.getMessage());
+ break;
default:
LOG.log(SEVERE, "Unsupported message type: "
+ fnc.getMessage());
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeLog.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeLog.java
index 1e03d1d..7b7bb70 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeLog.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeLog.java
@@ -28,7 +28,10 @@
package org.opends.server.tools.upgrade;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
@@ -37,6 +40,9 @@
import java.util.logging.Logger;
import org.opends.messages.RuntimeMessages;
+import org.opends.server.tools.ClientException;
+
+import static org.opends.messages.ToolMessages.ERR_UPGRADE_INVALID_LOG_FILE;
/**
* Creates a historical log about the upgrade. If file does not exist an attempt
@@ -104,4 +110,24 @@
logger.log(Level.CONFIG, RuntimeMessages.NOTE_INSTANCE_DIRECTORY.get(
UpgradeUtils.getInstancePath()).toString());
}
+
+ /**
+ * Returns the print stream of the current logger.
+ *
+ * @return the print stream of the current logger.
+ * @throws ClientException
+ * If the file defined by the logger is not found or invalid.
+ */
+ static PrintStream getPrintStream() throws ClientException
+ {
+ try
+ {
+ return new PrintStream(new FileOutputStream(logFile, true));
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new ClientException(1, ERR_UPGRADE_INVALID_LOG_FILE.get(e
+ .getMessage()));
+ }
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTask.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTask.java
index f433ddc..968cacd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTask.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTask.java
@@ -62,20 +62,6 @@
}
/**
- * Notifies this task that the upgrade has completed. This method will be
- * invoked after all upgrade tasks have completed successfully. Most task
- * implementation will not need to do anything.
- *
- * @param context
- * Context through which tasks can interact with the server
- * installation.
- * @throws ClientException
- * If an error occurred while performing the task.
- */
- void end(UpgradeContext context)
- throws ClientException;
-
- /**
* Performs this upgrade task.
*
* @param context
@@ -126,4 +112,29 @@
*/
void interact(UpgradeContext context)
throws ClientException;
+
+ /**
+ * This method will be invoked after all upgrade tasks have completed
+ * successfully The post upgrade tasks are processes which should be launched
+ * after a successful upgrade.
+ *
+ * @param context
+ * Context through which tasks can interact with the server
+ * installation.
+ * @throws ClientException
+ * If the task cannot proceed.
+ */
+ void postUpgrade(UpgradeContext context) throws ClientException;
+
+ /**
+ * This method will be invoked only if one of the previous post upgrade task
+ * has failed.
+ *
+ * @param context
+ * Context through which tasks can interact with the server
+ * installation.
+ * @throws ClientException
+ * If the task cannot proceed.
+ */
+ void postponePostUpgrade(UpgradeContext context) throws ClientException;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java
index 9181072..de87f2a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java
@@ -31,20 +31,28 @@
import static org.opends.server.tools.ToolConstants.OPTION_LONG_FORCE_UPGRADE;
import static org.opends.server.tools.ToolConstants.OPTION_LONG_NO_PROMPT;
import static org.opends.server.tools.upgrade.FileManager.copy;
+import static org.opends.server.tools.upgrade.Installation
+.CURRENT_CONFIG_FILE_NAME;
import static org.opends.server.tools.upgrade.Upgrade.*;
import static org.opends.server.tools.upgrade.UpgradeUtils.*;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.TextOutputCallback;
import org.opends.messages.Message;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.tools.ClientException;
+import org.opends.server.tools.RebuildIndex;
import org.opends.server.tools.upgrade.UpgradeTask.TaskType;
import org.opends.server.util.BuildVersion;
import org.opends.server.util.ChangeOperationType;
@@ -66,6 +74,16 @@
.getLogger(UpgradeCli.class.getName());
/**
+ * The indexes list to rebuild are united here.
+ */
+ static Set<String> indexesListToRebuild = new HashSet<String>();
+
+ /**
+ * A flag to avoid rebuild indexes if all already selected.
+ */
+ static boolean isRebuildAllIndexes = false;
+
+ /**
* Returns a new upgrade task which applies an LDIF record to all
* configuration entries matching the provided filter.
*
@@ -412,19 +430,34 @@
}
@Override
- public void end(UpgradeContext context) throws ClientException
+ public void postUpgrade(UpgradeContext context) throws ClientException
{
if (currentVersionEqualToOrMoreRecentThan(context, version))
{
- for (UpgradeTask task : tasks)
+ boolean isOk = true;
+ for (final UpgradeTask task : tasks)
{
- task.end(context);
+ if (isOk)
+ {
+ try
+ {
+ task.postUpgrade(context);
+ }
+ catch (ClientException e)
+ {
+ LOG.log(Level.SEVERE, e.getMessage());
+ isOk = false;
+ }
+ }
+ else
+ {
+ task.postponePostUpgrade(context);
+ }
}
}
}
-
private boolean currentVersionEqualToOrMoreRecentThan(
UpgradeContext context, final BuildVersion version)
{
@@ -447,7 +480,7 @@
@Override
public void perform(final UpgradeContext context) throws ClientException
{
- // TODO
+ // NYI.
}
@Override
@@ -467,48 +500,136 @@
/**
- * Creates a rebuild index task for a single index. At the moment this is
- * implemented as a simple stub which displays a message which should prompt
- * the user to rebuild the index manually once the upgrade has completed.
- * <p>
- * In future this task should register the index to be rebuilt in a table. A
- * subsequent task executed at the end of the upgrade process will then obtain
- * the set of indexes to be rebuilt, optimize it (e.g. removing duplicates),
- * and perform the rebuild.
+ * Creates a rebuild index task for a given single index. As this task is
+ * possibly lengthy, it's considered as a post upgrade task. This task is not
+ * mandatory; e.g not require user interaction, but could be required to get a
+ * fully functional server. <br />
+ * The post upgrade task just register the task. The rebuild indexes tasks are
+ * completed at the end of the upgrade process.
*
* @param summary
* A message describing why the index needs to be rebuilt and asking
- * them whether or not they wish to continue.
+ * them whether or not they wish to perform this task after the
+ * upgrade.
+ * @param index
+ * The index to rebuild.
* @return The rebuild index task.
*/
- public static UpgradeTask rebuildSingleIndex(final Message summary)
+ public static UpgradeTask rebuildSingleIndex(final Message summary,
+ final String index)
{
return new AbstractUpgradeTask()
{
- @Override
- public void verify(final UpgradeContext context) throws ClientException
- {
- verifyTaskType(TaskType.MANDATORY_USER_INTERACTION, context);
- }
+ private boolean isATaskToPerform = false;
@Override
public void interact(UpgradeContext context) throws ClientException
{
- // Require acknowledgment from the user.
+ Upgrade.setHasPostUpgradeTask(true);
+ // Requires answer from the user.
final int answer = context.confirmYN(summary, ConfirmationCallback.NO);
+ isATaskToPerform = (answer == ConfirmationCallback.YES);
+ }
- // The user refused to perform this task.
- if (answer == ConfirmationCallback.NO)
+ @Override
+ public void postUpgrade(final UpgradeContext context)
+ throws ClientException
+ {
+ if (isATaskToPerform)
{
- throw new ClientException(EXIT_CODE_MANUAL_INTERVENTION,
- INFO_UPGRADE_ABORTED_BY_USER.get());
+ indexesListToRebuild.add(index);
+ }
+ else
+ {
+ postponePostUpgrade(context);
}
}
@Override
- public void perform(final UpgradeContext context) throws ClientException
+ public void postponePostUpgrade(UpgradeContext context)
+ throws ClientException
{
- // TODO: automatic rebuild is not supported yet.
+ context.notify(INFO_UPGRADE_REBUILD_INDEX_DECLINED.get(index),
+ TextOutputCallback.WARNING);
+ }
+ };
+ }
+
+ /**
+ * This task is processed at the end of the upgrade, rebuilding indexes. If a
+ * rebuild all indexes has been registered before, it takes the flag
+ * relatively to single rebuild index.
+ *
+ * @return The post upgrade rebuild indexes task.
+ */
+ public static UpgradeTask postUpgradeRebuildIndexes()
+ {
+ return new AbstractUpgradeTask()
+ {
+ @Override
+ public void postUpgrade(final UpgradeContext context)
+ throws ClientException
+ {
+ if (isRebuildAllIndexes)
+ {
+ // TODO To implement
+ }
+ else if (!indexesListToRebuild.isEmpty())
+ {
+ final Message message = INFO_UPGRADE_REBUILD_INDEX_STARTS.get(Arrays
+ .toString(indexesListToRebuild.toArray()));
+ final ProgressNotificationCallback pnc =
+ new ProgressNotificationCallback(0, message, 25);
+ LOG.log(Level.INFO, message.toString());
+ context.notifyProgress(pnc);
+
+ // Sets the arguments like the rebuild index command line.
+ final List<String> args = new LinkedList<String>();
+ args.addAll(Arrays.asList(
+ "-f",
+ new File(configDirectory, CURRENT_CONFIG_FILE_NAME)
+ .getAbsolutePath()));
+
+ // Adding all requested indexes.
+ for (final String indexToRebuild : indexesListToRebuild)
+ {
+ args.add("-i");
+ args.add(indexToRebuild);
+ }
+
+ // Index(es) could be contained in several backends.
+ for (final String be : UpgradeUtils.getLocalBackendsFromConfig())
+ {
+ args.add("-b");
+ args.add(be);
+ }
+
+ final String[] commandLineArgs =
+ args.toArray(new String[args.size()]);
+ // Displays info about command line args for log only.
+ LOG.log(Level.INFO, INFO_UPGRADE_REBUILD_INDEX_ARGUMENTS.get(Arrays
+ .toString(commandLineArgs)).toString());
+ /*
+ * The rebuild-index process just display a status ok / fails. The
+ * logger stream contains all the log linked to this process. The
+ * complete process is not displayed in the upgrade console.
+ */
+ final int result =
+ new RebuildIndex().rebuildIndexesWithinMultipleBackends(true,
+ UpgradeLog.getPrintStream(), commandLineArgs);
+ if (result == 0)
+ {
+ LOG.log(Level.INFO, INFO_UPGRADE_REBUILD_INDEX_ENDS.get()
+ .toString());
+ context.notifyProgress(pnc.setProgress(100));
+ }
+ else
+ {
+ LOG.log(Level.SEVERE, ERR_UPGRADE_PERFORMING_POST_TASKS_FAIL.get()
+ .toString());
+ context.notifyProgress(pnc.setProgress(-100));
+ }
+ }
}
};
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java
index b03c56c..c73e57c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java
@@ -28,8 +28,7 @@
import java.io.*;
import java.util.LinkedList;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -386,21 +385,21 @@
return installationPath;
}
- // This function is not in use actually but may be useful later
- // eg. for rebuild index task.
- @SuppressWarnings("unused")
- private static SortedMap<String, LinkedList<String>> getLocalBackends()
+ /**
+ * Retrieves the backends from the current configuration file.
+ *
+ * @return A backend list.
+ */
+ static List<String> getLocalBackendsFromConfig()
{
- // Config.ldif path
- final File configLdif = new File(configDirectory,
- CURRENT_CONFIG_FILE_NAME);
- SortedMap<String, LinkedList<String>> result =
- new TreeMap<String, LinkedList<String>>();
-
+ final List<String> listBackends = new LinkedList<String>();
LDIFEntryReader entryReader = null;
try
{
- entryReader = new LDIFEntryReader(new FileInputStream(configLdif));
+ entryReader =
+ new LDIFEntryReader(new FileInputStream(new File(configDirectory,
+ CURRENT_CONFIG_FILE_NAME)));
+
final Filter filter =
Filter.equality("objectclass", "ds-cfg-local-db-backend");
final Matcher includeFilter = filter.matcher();
@@ -408,21 +407,9 @@
while (entryReader.hasNext())
{
- LinkedList<String> dataRelativesToBck = new LinkedList<String>();
- Entry entry = entryReader.readEntry();
- // Backend dn
- dataRelativesToBck.add(entry.getAttribute("ds-cfg-base-dn")
+ final Entry entry = entryReader.readEntry();
+ listBackends.add(entry.getAttribute("ds-cfg-base-dn")
.firstValueAsString());
- // db path
- dataRelativesToBck.add(entry.getAttribute("ds-cfg-db-directory")
- .firstValueAsString());
- // enabled ?
- dataRelativesToBck.add(entry.getAttribute("ds-cfg-enabled")
- .firstValueAsString());
- // backend name
- result.put(
- entry.getAttribute("ds-cfg-backend-id").firstValueAsString(),
- dataRelativesToBck);
}
}
catch (Exception ex)
@@ -434,7 +421,7 @@
StaticUtils.close(entryReader);
}
- return result;
+ return listBackends;
}
/**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java b/opendj-sdk/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java
index f475576..e09a564 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java
@@ -129,6 +129,10 @@
* Defines a breakline.
*/
BREAKLINE,
+ /**
+ * Defines a warning.
+ */
+ WARNING
}
// The error stream which this application should use.
@@ -448,6 +452,9 @@
case BREAKLINE:
out.println();
break;
+ case WARNING:
+ out.println(wrapText("[!] " + msg, MAX_LINE_WIDTH, indent));
+ break;
default:
out.println(wrapText(msg, MAX_LINE_WIDTH, indent));
break;
--
Gitblit v1.10.0