From 3af39927fd1bba93a2769cd5d6bc7b6c5f924c64 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Sun, 02 Sep 2007 01:12:13 +0000
Subject: [PATCH] Update the server so that it has the ability to save a copy of its current configuration into a ".startok" file whenever it starts successfully. The start-ds script and DirectoryEnvironmentConfig class have been updated to expose an option to try to start the server using this "last known good" configuration rather than the active config file.
---
opends/resource/schema/02-config.ldif | 7
opends/src/messages/messages/config.properties | 17 +
opends/src/server/org/opends/server/core/DirectoryServer.java | 71 ++++++-
opends/src/messages/messages/core.properties | 3
opends/src/server/org/opends/server/api/ConfigHandler.java | 20 ++
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ConfigFileHandlerTestCase.java | 14 +
opends/src/server/org/opends/server/extensions/ConfigFileHandler.java | 268 ++++++++++++++++++++++++++---
opends/resource/config/config.ldif | 1
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml | 26 ++
opends/src/server/org/opends/server/core/CoreConfigManager.java | 3
opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java | 71 +++++++
opends/src/server/org/opends/server/util/ServerConstants.java | 10 +
12 files changed, 472 insertions(+), 39 deletions(-)
diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index d20663e..0bd7b5c 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -48,6 +48,7 @@
ds-cfg-default-password-policy: cn=Default Password Policy,cn=Password Policies,cn=config
ds-cfg-return-bind-error-messages: false
ds-cfg-idle-time-limit: 0 seconds
+ds-cfg-save-config-on-successful-startup: true
ds-cfg-allowed-task: org.opends.server.tasks.AddSchemaFileTask
ds-cfg-allowed-task: org.opends.server.tasks.BackupTask
ds-cfg-allowed-task: org.opends.server.tasks.DisconnectClientTask
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 1a90fba..9c9b6b9 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1611,6 +1611,10 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.478
NAME 'ds-cfg-message-template-file' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.485
+ NAME 'ds-cfg-save-config-on-successful-startup'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1830,7 +1834,8 @@
ds-cfg-reject-unauthenticated-requests $
ds-cfg-bind-with-dn-requires-password $ ds-cfg-lookthrough-limit $
ds-cfg-smtp-server $ ds-cfg-allowed-task $ ds-cfg-disabled-privilege $
- ds-cfg-return-bind-error-messages $ ds-cfg-idle-time-limit )
+ ds-cfg-return-bind-error-messages $ ds-cfg-idle-time-limit $
+ ds-cfg-save-config-on-successful-startup )
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.41 NAME 'ds-cfg-root-dn' SUP top
AUXILIARY MAY ds-cfg-alternate-bind-dn X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
index 0949ecb..2561d3d 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -702,7 +702,7 @@
<adm:property name="idle-time-limit" mandatory="false" multi-valued="false">
<adm:synopsis>
- Specifies the maximum lenght of time that a client connection may remain
+ Specifies the maximum length of time that a client connection may remain
established since its last completed operation. A value of "0 seconds"
indicates that no idle time limit will be enforced.
</adm:synopsis>
@@ -722,5 +722,29 @@
</adm:profile>
</adm:property>
+ <adm:property name="save-config-on-successful-startup" mandatory="false">
+ <adm:synopsis>
+ Indicates whether the Directory Server should save a copy of its
+ configuration whenever the startup process completes successfully. This
+ can ensure that the server provides a "last known good" configuration,
+ which can be used as a reference (or copied into the active config) if the
+ server fails to start with the current "active" configuration.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>true</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:boolean />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.485</ldap:oid>
+ <ldap:name>ds-cfg-save-config-on-successful-startup</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+
</adm:managed-object>
diff --git a/opends/src/messages/messages/config.properties b/opends/src/messages/messages/config.properties
index 51b3003..cc0b3ab 100644
--- a/opends/src/messages/messages/config.properties
+++ b/opends/src/messages/messages/config.properties
@@ -2131,3 +2131,20 @@
'%s' is invalid. An SMTP server value must have an IP address or a \
resolvable name, and it may optionally be followed by a colon and an integer \
value between 1 and 65535 to specify the server port number
+SEVERE_ERR_STARTOK_CANNOT_OPEN_FOR_READING_698=An error occurred while \
+ attempting to open the current configuration file %s for reading in order to \
+ copy it to the ".startok" file: %s
+SEVERE_ERR_STARTOK_CANNOT_OPEN_FOR_WRITING_699=An error occurred while \
+ attempting to open file %s in order to write the ".startok" configuration \
+ file: %s
+SEVERE_ERR_STARTOK_CANNOT_WRITE_700=An error occurred while attempting to \
+ copy the current configuration from file %s into temporary file %s for use \
+ as the ".startok" configuration file: %s
+SEVERE_ERR_STARTOK_CANNOT_RENAME_701=An error occurred while attempting to \
+ rename file %s to %s for use as the ".startok" configuration file: %s
+NOTICE_CONFIG_FILE_USING_STARTOK_FILE_702=The Directory Server is starting \
+ using the last known good configuration file %s rather than the active \
+ configuration file %s
+SEVERE_WARN_CONFIG_FILE_NO_STARTOK_FILE_703=No last known good configuration \
+ file %s exists. The server will attempt to start using the active \
+ configuration file %s
diff --git a/opends/src/messages/messages/core.properties b/opends/src/messages/messages/core.properties
index 23478ba..c65a87e 100644
--- a/opends/src/messages/messages/core.properties
+++ b/opends/src/messages/messages/core.properties
@@ -1652,3 +1652,6 @@
store backend %s is not enabled
SEVERE_ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_WRONG_CLASS_651=The backend %s \
is not a trust store backend
+INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG_652=Attempt to start using the \
+ configuration that was in place at the last successful startup (if it is \
+ available) rather than using the current active configuration
diff --git a/opends/src/server/org/opends/server/api/ConfigHandler.java b/opends/src/server/org/opends/server/api/ConfigHandler.java
index 5c8701e..5f1a563 100644
--- a/opends/src/server/org/opends/server/api/ConfigHandler.java
+++ b/opends/src/server/org/opends/server/api/ConfigHandler.java
@@ -132,5 +132,25 @@
*/
public abstract void writeUpdatedConfig()
throws DirectoryException;
+
+
+
+ /**
+ * Indicates that the Directory Server has started successfully and
+ * that the configuration handler should save a copy of the current
+ * configuration for use as a "last known good" reference. Note
+ * that this may not be possible with some kinds of configuration
+ * repositories, so it should be a best effort attempt.
+ * <BR><BR>
+ * This method should only be called by the Directory Server itself
+ * when the server has started successfully. It should not be
+ * invoked by any other component at any other time.
+ */
+ @org.opends.server.types.PublicAPI(
+ stability=org.opends.server.types.StabilityLevel.VOLATILE,
+ mayInstantiate=false,
+ mayExtend=true,
+ mayInvoke=false)
+ public abstract void writeSuccessfulStartupConfig();
}
diff --git a/opends/src/server/org/opends/server/core/CoreConfigManager.java b/opends/src/server/org/opends/server/core/CoreConfigManager.java
index 13960ac..a9bf894 100644
--- a/opends/src/server/org/opends/server/core/CoreConfigManager.java
+++ b/opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -337,6 +337,9 @@
globalConfig.isReturnBindErrorMessages());
DirectoryServer.setIdleTimeLimit(globalConfig.getIdleTimeLimit());
+
+ DirectoryServer.setSaveConfigOnSuccessfulStartup(
+ globalConfig.isSaveConfigOnSuccessfulStartup());
}
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 028bad1..c5efb40 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -359,6 +359,10 @@
// been abandoned.
private boolean notifyAbandonedOperations;
+ // Indicates whether to save a copy of the configuration on successful
+ // startup.
+ private boolean saveConfigOnSuccessfulStartup;
+
// Indicates whether the server is currently in the process of shutting down.
private boolean shuttingDown;
@@ -1428,6 +1432,14 @@
}
+ // If we should write a copy of the config on successful startup, then do
+ // so now.
+ if (saveConfigOnSuccessfulStartup)
+ {
+ configHandler.writeSuccessfulStartupConfig();
+ }
+
+
// Mark the current time as the start time and indicate that the server is
// now running.
startUpTime = System.currentTimeMillis();
@@ -7727,6 +7739,37 @@
/**
+ * Indicates whether the Directory Server should save a copy of its
+ * configuration whenever it is started successfully.
+ *
+ * @return {@code true} if the server should save a copy of its configuration
+ * whenever it is started successfully, or {@code false} if not.
+ */
+ public static boolean saveConfigOnSuccessfulStartup()
+ {
+ return directoryServer.saveConfigOnSuccessfulStartup;
+ }
+
+
+
+ /**
+ * Specifies whether the Directory Server should save a copy of its
+ * configuration whenever it is started successfully.
+ *
+ * @param saveConfigOnSuccessfulStartup Specifies whether the server should
+ * save a copy of its configuration
+ * whenever it is started successfully.
+ */
+ public static void setSaveConfigOnSuccessfulStartup(
+ boolean saveConfigOnSuccessfulStartup)
+ {
+ directoryServer.saveConfigOnSuccessfulStartup =
+ saveConfigOnSuccessfulStartup;
+ }
+
+
+
+ /**
* Registers the provided backup task listener with the Directory Server.
*
* @param listener The backup task listener to register with the Directory
@@ -8999,15 +9042,16 @@
public static void main(String[] args)
{
// Define the arguments that may be provided to the server.
- BooleanArgument checkStartability = null;
- BooleanArgument quietMode = null;
- BooleanArgument windowsNetStart = null;
- BooleanArgument displayUsage = null;
- BooleanArgument fullVersion = null;
- BooleanArgument noDetach = null;
- BooleanArgument systemInfo = null;
- StringArgument configClass = null;
- StringArgument configFile = null;
+ BooleanArgument checkStartability = null;
+ BooleanArgument quietMode = null;
+ BooleanArgument windowsNetStart = null;
+ BooleanArgument displayUsage = null;
+ BooleanArgument fullVersion = null;
+ BooleanArgument noDetach = null;
+ BooleanArgument systemInfo = null;
+ BooleanArgument useLastKnownGoodConfig = null;
+ StringArgument configClass = null;
+ StringArgument configFile = null;
// Create the command-line argument parser for use with this program.
@@ -9064,6 +9108,13 @@
argParser.addArgument(systemInfo);
+ useLastKnownGoodConfig =
+ new BooleanArgument("lastknowngoodconfig", 'L',
+ "useLastKnownGoodConfig",
+ INFO_DSCORE_DESCRIPTION_LASTKNOWNGOODCFG.get());
+ argParser.addArgument(useLastKnownGoodConfig);
+
+
noDetach = new BooleanArgument("nodetach", 'N', "nodetach",
INFO_DSCORE_DESCRIPTION_NODETACH.get());
argParser.addArgument(noDetach);
@@ -9389,6 +9440,8 @@
configClass.getValue());
environmentConfig.setProperty(PROPERTY_CONFIG_FILE,
configFile.getValue());
+ environmentConfig.setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG,
+ String.valueOf(useLastKnownGoodConfig.isPresent()));
startupErrorLogPublisher =
diff --git a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
index 54bfa16..228105f 100644
--- a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
+++ b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -25,7 +25,6 @@
* Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.extensions;
-import org.opends.messages.Message;
@@ -60,6 +59,7 @@
import javax.crypto.CipherOutputStream;
import javax.crypto.Mac;
+import org.opends.messages.Message;
import org.opends.server.api.AlertGenerator;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConfigAddListener;
@@ -135,6 +135,9 @@
// Indicates whether to maintain a configuration archive.
private boolean maintainConfigArchive;
+ // Indicates whether to start using the last known good configuration.
+ private boolean useLastKnownGoodConfig;
+
// A SHA-1 digest of the last known configuration. This should only be
// incorrect if the server configuration file has been manually edited with
// the server online, which is a bad thing.
@@ -199,15 +202,41 @@
configLock = new ReentrantLock();
- // Make sure that the configuration file exists.
+ // Determine whether we should try to start using the last known good
+ // configuration. If so, then only do so if such a file exists. If it
+ // doesn't exist, then fall back on the active configuration file.
this.configFile = configFile;
- File f = new File(configFile);
+ DirectoryEnvironmentConfig envConfig =
+ DirectoryServer.getEnvironmentConfig();
+ useLastKnownGoodConfig = envConfig.useLastKnownGoodConfiguration();
+ File f = null;
+ if (useLastKnownGoodConfig)
+ {
+ f = new File(configFile + ".startok");
+ if (! f.exists())
+ {
+ logError(WARN_CONFIG_FILE_NO_STARTOK_FILE.get(f.getAbsolutePath(),
+ configFile));
+ useLastKnownGoodConfig = false;
+ f = new File(configFile);
+ }
+ else
+ {
+ logError(NOTE_CONFIG_FILE_USING_STARTOK_FILE.get(f.getAbsolutePath(),
+ configFile));
+ }
+ }
+ else
+ {
+ f = new File(configFile);
+ }
try
{
if (! f.exists())
{
- Message message = ERR_CONFIG_FILE_DOES_NOT_EXIST.get(configFile);
+ Message message = ERR_CONFIG_FILE_DOES_NOT_EXIST.get(
+ f.getAbsolutePath());
throw new InitializationException(message);
}
}
@@ -228,7 +257,7 @@
}
Message message = ERR_CONFIG_FILE_CANNOT_VERIFY_EXISTENCE.get(
- configFile, String.valueOf(e));
+ f.getAbsolutePath(), String.valueOf(e));
throw new InitializationException(message);
}
@@ -236,11 +265,9 @@
// Check to see if a configuration archive exists. If not, then create one.
// If so, then check whether the current configuration matches the last
// configuration in the archive. If it doesn't, then archive it.
- DirectoryEnvironmentConfig envConfig =
- DirectoryServer.getEnvironmentConfig();
maintainConfigArchive = envConfig.maintainConfigArchive();
maxConfigArchiveSize = envConfig.getMaxConfigArchiveSize();
- if (maintainConfigArchive)
+ if (maintainConfigArchive & (! useLastKnownGoodConfig))
{
try
{
@@ -307,7 +334,7 @@
LDIFReader reader;
try
{
- LDIFImportConfig importConfig = new LDIFImportConfig(configFile);
+ LDIFImportConfig importConfig = new LDIFImportConfig(f.getAbsolutePath());
// FIXME -- Should we support encryption or compression for the config?
@@ -321,7 +348,7 @@
}
Message message = ERR_CONFIG_FILE_CANNOT_OPEN_FOR_READ.get(
- configFile, String.valueOf(e));
+ f.getAbsolutePath(), String.valueOf(e));
throw new InitializationException(message, e);
}
@@ -352,7 +379,7 @@
}
Message message = ERR_CONFIG_FILE_INVALID_LDIF_ENTRY.get(
- le.getLineNumber(), configFile, String.valueOf(le));
+ le.getLineNumber(), f.getAbsolutePath(), String.valueOf(le));
throw new InitializationException(message, le);
}
catch (Exception e)
@@ -375,7 +402,8 @@
}
Message message =
- ERR_CONFIG_FILE_READ_ERROR.get(configFile, String.valueOf(e));
+ ERR_CONFIG_FILE_READ_ERROR.get(f.getAbsolutePath(),
+ String.valueOf(e));
throw new InitializationException(message, e);
}
@@ -395,7 +423,7 @@
}
}
- Message message = ERR_CONFIG_FILE_EMPTY.get(configFile);
+ Message message = ERR_CONFIG_FILE_EMPTY.get(f.getAbsolutePath());
throw new InitializationException(message);
}
@@ -407,7 +435,8 @@
if (! entry.getDN().equals(configRootDN))
{
Message message = ERR_CONFIG_FILE_INVALID_BASE_DN.get(
- configFile, entry.getDN().toString(), DN_CONFIG_ROOT);
+ f.getAbsolutePath(), entry.getDN().toString(),
+ DN_CONFIG_ROOT);
throw new InitializationException(message);
}
}
@@ -452,8 +481,8 @@
}
// This should not happen, so we can use a generic error here.
- Message message =
- ERR_CONFIG_FILE_GENERIC_ERROR.get(configFile, String.valueOf(e));
+ Message message = ERR_CONFIG_FILE_GENERIC_ERROR.get(f.getAbsolutePath(),
+ String.valueOf(e));
throw new InitializationException(message, e);
}
@@ -494,7 +523,8 @@
}
Message message = ERR_CONFIG_FILE_INVALID_LDIF_ENTRY.get(
- le.getLineNumber(), configFile, String.valueOf(le));
+ le.getLineNumber(), f.getAbsolutePath(),
+ String.valueOf(le));
throw new InitializationException(message, le);
}
catch (Exception e)
@@ -516,8 +546,8 @@
}
}
- Message message =
- ERR_CONFIG_FILE_READ_ERROR.get(configFile, String.valueOf(e));
+ Message message = ERR_CONFIG_FILE_READ_ERROR.get(f.getAbsolutePath(),
+ String.valueOf(e));
throw new InitializationException(message, e);
}
@@ -559,8 +589,9 @@
}
Message message = ERR_CONFIG_FILE_DUPLICATE_ENTRY.get(
- entryDN.toString(), String.valueOf(reader.getLastEntryLineNumber()),
- configFile);
+ entryDN.toString(),
+ String.valueOf(reader.getLastEntryLineNumber()),
+ f.getAbsolutePath());
throw new InitializationException(message);
}
@@ -582,7 +613,9 @@
}
Message message = ERR_CONFIG_FILE_UNKNOWN_PARENT.get(
- entryDN.toString(), reader.getLastEntryLineNumber(), configFile);
+ entryDN.toString(),
+ reader.getLastEntryLineNumber(),
+ f.getAbsolutePath());
throw new InitializationException(message);
}
@@ -601,9 +634,9 @@
}
}
- Message message = ERR_CONFIG_FILE_NO_PARENT.
- get(entryDN.toString(), reader.getLastEntryLineNumber(), configFile,
- parentDN.toString());
+ Message message = ERR_CONFIG_FILE_NO_PARENT.get(entryDN.toString(),
+ reader.getLastEntryLineNumber(),
+ f.getAbsolutePath(), parentDN.toString());
throw new InitializationException(message);
}
@@ -636,8 +669,8 @@
}
}
- Message message =
- ERR_CONFIG_FILE_GENERIC_ERROR.get(configFile, String.valueOf(e));
+ Message message = ERR_CONFIG_FILE_GENERIC_ERROR.get(f.getAbsolutePath(),
+ String.valueOf(e));
throw new InitializationException(message, e);
}
}
@@ -651,7 +684,7 @@
{
try
{
- File configDirFile = new File(configFile).getParentFile();
+ File configDirFile = f.getParentFile();
if ((configDirFile != null) &&
configDirFile.getName().equals(CONFIG_DIR_NAME))
{
@@ -2265,6 +2298,185 @@
/**
+ * {@inheritDoc}
+ */
+ public void writeSuccessfulStartupConfig()
+ {
+ if (useLastKnownGoodConfig)
+ {
+ // The server was started with the "last known good" configuration, so we
+ // shouldn't overwrite it with something that is probably bad.
+ return;
+ }
+
+
+ String startOKFilePath = configFile + ".startok";
+ String tempFilePath = startOKFilePath + ".tmp";
+ String oldFilePath = startOKFilePath + ".old";
+
+
+ // Copy the current config file to a temporary file.
+ File tempFile = new File(tempFilePath);
+ FileInputStream inputStream = null;
+ try
+ {
+ inputStream = new FileInputStream(configFile);
+
+ FileOutputStream outputStream = null;
+ try
+ {
+ outputStream = new FileOutputStream(tempFilePath, false);
+
+ try
+ {
+ byte[] buffer = new byte[8192];
+ while (true)
+ {
+ int bytesRead = inputStream.read(buffer);
+ if (bytesRead < 0)
+ {
+ break;
+ }
+
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ logError(ERR_STARTOK_CANNOT_WRITE.get(configFile, tempFilePath,
+ getExceptionMessage(e)));
+ return;
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ logError(ERR_STARTOK_CANNOT_OPEN_FOR_WRITING.get(tempFilePath,
+ getExceptionMessage(e)));
+ return;
+ }
+ finally
+ {
+ try
+ {
+ outputStream.close();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ logError(ERR_STARTOK_CANNOT_OPEN_FOR_READING.get(configFile,
+ getExceptionMessage(e)));
+ return;
+ }
+ finally
+ {
+ try
+ {
+ inputStream.close();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+
+
+ // If a ".startok" file already exists, then move it to an ".old" file.
+ File oldFile = new File(oldFilePath);
+ try
+ {
+ if (oldFile.exists())
+ {
+ oldFile.delete();
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+ File startOKFile = new File(startOKFilePath);
+ try
+ {
+ if (startOKFile.exists())
+ {
+ startOKFile.renameTo(oldFile);
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+
+ // Rename the temp file to the ".startok" file.
+ try
+ {
+ tempFile.renameTo(startOKFile);
+ } catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ logError(ERR_STARTOK_CANNOT_RENAME.get(tempFilePath, startOKFilePath,
+ getExceptionMessage(e)));
+ return;
+ }
+
+
+ // Remove the ".old" file if there is one.
+ try
+ {
+ if (oldFile.exists())
+ {
+ oldFile.delete();
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+
+
+
+ /**
* Retrieves the OIDs of the controls that may be supported by this backend.
*
* @return The OIDs of the controls that may be supported by this backend.
diff --git a/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java b/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
index dcf9c6b..3d3d8f0 100644
--- a/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
+++ b/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
@@ -470,6 +470,77 @@
/**
+ * Indicates whether the Directory Server should attempt to start
+ * with the "last known good" configuration rather than the current
+ * active configuration file. Note that if there is no "last known
+ * good" configuration file available, then the server should try to
+ * start using the current, active configuration file. If no
+ * explicit value is defined, then a default result of {@code false}
+ * will be returned.
+ *
+ * @return {@code true} if the Directory Server should attempt to
+ * start using the "last known good" configuration, or
+ * {@code false} if it should try to start using the
+ * active configuration.
+ */
+ public boolean useLastKnownGoodConfiguration()
+ {
+ String useLastKnownGoodStr =
+ getProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG);
+ if (useLastKnownGoodStr == null)
+ {
+ return false;
+ }
+
+ return useLastKnownGoodStr.equalsIgnoreCase("true");
+ }
+
+
+
+ /**
+ * Specifies whether the Directory Server should attempt to start
+ * using the last known good configuration rather than the
+ * current active configuration.
+ *
+ * @param useLastKnownGoodConfiguration Indicates whether the
+ * Directory Server should
+ * attempt to start using the
+ * last known good
+ * configuration.
+ *
+ * @return The previous setting for this configuration option. If
+ * no previous value was specified, then {@code false} will
+ * be returned.
+ *
+ * @throws InitializationException If the Directory Server is
+ * already running.
+ */
+ public boolean setUseLastKnownGoodConfiguration(
+ boolean useLastKnownGoodConfiguration)
+ throws InitializationException
+ {
+ if (DirectoryServer.isRunning())
+ {
+ throw new InitializationException(
+ ERR_DIRCFG_SERVER_ALREADY_RUNNING.get());
+ }
+
+ String oldUseLastKnownGoodStr =
+ setProperty(PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG,
+ String.valueOf(useLastKnownGoodConfiguration));
+ if (oldUseLastKnownGoodStr == null)
+ {
+ return false;
+ }
+ else
+ {
+ return oldUseLastKnownGoodStr.equalsIgnoreCase("true");
+ }
+ }
+
+
+
+ /**
* Indicates whether the Directory Server should maintain an archive
* of previous configurations. If no explicit value is defined,
* then a default result of {@code true} will be returned.
diff --git a/opends/src/server/org/opends/server/util/ServerConstants.java b/opends/src/server/org/opends/server/util/ServerConstants.java
index 23fab11..336772f 100644
--- a/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -2612,6 +2612,16 @@
/**
+ * The name of the system property that can be used to indicate that the
+ * Directory Server should attempt to start using the last known good
+ * configuration, rather than the current active configuration.
+ */
+ public static final String PROPERTY_USE_LAST_KNOWN_GOOD_CONFIG =
+ "org.opends.server.UseLastKnownGoodConfiguration";
+
+
+
+ /**
* The column at which to wrap long lines of output in the command-line tools.
*/
public static final int MAX_LINE_WIDTH;
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ConfigFileHandlerTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ConfigFileHandlerTestCase.java
index 199406b..0e4ed1f 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ConfigFileHandlerTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/ConfigFileHandlerTestCase.java
@@ -28,6 +28,7 @@
+import java.io.File;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
@@ -60,6 +61,19 @@
throws Exception
{
TestCaseUtils.startServer();
+
+ String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
+ String startOKFile = buildRoot + File.separator + "build" + File.separator +
+ "unit-tests" + File.separator + "package" +
+ File.separator + "config" + File.separator +
+ "config.ldif.startok";
+
+ assertTrue(new File(startOKFile).exists(),
+ startOKFile + " does not exist but it should");
+ assertFalse(new File(startOKFile + ".tmp").exists(),
+ startOKFile + ".tmp exists but should not");
+ assertFalse(new File(startOKFile + ".old").exists(),
+ startOKFile + ".old exists but should not");
}
--
Gitblit v1.10.0