From 2580308b1458e703715ffc637dd93c56d199ba91 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 18 Dec 2006 01:28:08 +0000
Subject: [PATCH] Update the config file handler to change the way that the configuration archive is maintained. Rather than keeping the archive as a single zip file, it is now maintained as a directory of gzip-compressed files. This is much faster and more scalable. On my desktop machine, it reduces the time to run unit tests by about 75% (from about 7.5 minutes to less than 2 minutes).
---
opends/src/server/org/opends/server/extensions/ConfigFileHandler.java | 333 +++++++++++++++++++++++++------------------------------
1 files changed, 150 insertions(+), 183 deletions(-)
diff --git a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
index 7aad4f2..8ec35c3 100644
--- a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
+++ b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -44,6 +44,7 @@
import java.util.LinkedList;
import java.util.TreeMap;
import java.util.zip.Deflater;
+import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@@ -1560,185 +1561,138 @@
// FIXME -- This needs support for encryption.
- // Get the path to the current config file and then the path to the
- // directory containing that file.
- File f = new File(configFile);
- String configDirectory = f.getParent();
-
-
- // Open a temporary zip file for writing.
- String archiveName = configDirectory + File.separator + CONFIG_ARCHIVE_NAME;
- String tempArchive = archiveName + ".tmp";
- ZipOutputStream outputStream;
-
- try
+ // Try to write the configuration archive. If any part of this fails, then
+ // we'll abort that, but still try to write the updated configuration
+ // later.
+writeConfigArchive:
{
- outputStream = new ZipOutputStream(new FileOutputStream(tempArchive,
- false));
- }
- catch (Exception e)
- {
- assert debugException(CLASS_NAME, "writeUpdatedConfig", e);
-
- int msgID = MSGID_CONFIG_FILE_WRITE_CANNOT_CREATE_TEMP_ARCHIVE;
- String message = getMessage(msgID, String.valueOf(tempArchive),
- stackTraceToSingleLineString(e));
- logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.sendAlertNotification(this,
- ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
-
- return;
- }
+ // Determine the path to the directory that will hold the archived
+ // configuration files.
+ File configDirectory = new File(configFile).getParentFile();
+ File archiveDirectory = new File(configDirectory,
+ CONFIG_ARCHIVE_DIR_NAME);
- // Create a buffer to hold the information that we will read.
- byte[] buffer = new byte[8192];
+ // If the archive directory doesn't exist, then create it.
+ if (! archiveDirectory.exists())
+ {
+ try
+ {
+ if (! archiveDirectory.mkdirs())
+ {
+ int msgID = MSGID_CONFIG_FILE_CANNOT_CREATE_ARCHIVE_DIR_NO_REASON;
+ String message = getMessage(msgID,
+ archiveDirectory.getAbsolutePath());
+
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+
+ DirectoryServer.sendAlertNotification(this,
+ ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
+
+ break writeConfigArchive;
+ }
+ }
+ catch (Exception e)
+ {
+ assert debugException(CLASS_NAME, "writeUpdatedConfig", e);
+
+ int msgID = MSGID_CONFIG_FILE_CANNOT_CREATE_ARCHIVE_DIR;
+ String message = getMessage(msgID, archiveDirectory.getAbsolutePath(),
+ stackTraceToSingleLineString(e));
+
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+
+ DirectoryServer.sendAlertNotification(this,
+ ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
+
+ break writeConfigArchive;
+ }
+ }
- // Get a current timestamp that we will use as an extension for the config
- // file with the running configuration. This is necessary because we can't
- // have multiple files with the same name, so if there are multiple config
- // changes in the same second, then only the last one will be stored in the
- // archive (it will encapsulate the other changes as well, but it won't be
- // possible to determine that they were made in separate changes).
- String runningArchiveName = configFile + "." + TimeThread.getUTCTime();
-
-
- // See if there is an existing archive. If so, then read its contents and
- // write them into the new archive.
- File archiveFile = new File(archiveName);
- if (archiveFile.exists())
- {
+ // Determine the appropriate name to use for the current configuration.
+ File archiveFile;
try
{
- ZipInputStream inputStream =
- new ZipInputStream(new FileInputStream(archiveFile));
-
- ZipEntry zipEntry = inputStream.getNextEntry();
- while (zipEntry != null)
+ String timestamp = TimeThread.getUTCTime();
+ archiveFile = new File(archiveDirectory, "config-" + timestamp + ".gz");
+ if (archiveFile.exists())
{
- if (zipEntry.getName().equals(runningArchiveName))
+ int counter = 2;
+ archiveFile = new File(archiveDirectory,
+ "config-" + timestamp + "-" + counter + ".gz");
+
+ while (archiveFile.exists())
{
- // This entry has a name that is the same as what we will use for
- // archiving the running config, so we will skip it. It's almost
- // a guarantee that there won't be any more entries, but we can keep
- // going to make sure.
- zipEntry = inputStream.getNextEntry();
- continue;
+ counter++;
+ archiveFile = new File(archiveDirectory,
+ "config-" + timestamp + "." + counter +
+ ".gz");
}
-
- outputStream.putNextEntry(zipEntry);
-
- int bytesRead = inputStream.read(buffer);
- while (bytesRead > 0)
- {
- outputStream.write(buffer, 0, bytesRead);
- bytesRead = inputStream.read(buffer);
- }
-
- outputStream.closeEntry();
- zipEntry = inputStream.getNextEntry();
}
-
- inputStream.close();
}
catch (Exception e)
{
assert debugException(CLASS_NAME, "writeUpdatedConfig", e);
- int msgID = MSGID_CONFIG_FILE_WRITE_CANNOT_COPY_EXISTING_ARCHIVE;
- String message = getMessage(msgID, String.valueOf(archiveName),
- String.valueOf(tempArchive),
- stackTraceToSingleLineString(e));
- logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
+ int msgID = MSGID_CONFIG_FILE_CANNOT_WRITE_CONFIG_ARCHIVE;
+ String message = getMessage(msgID, stackTraceToSingleLineString(e));
+
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_ERROR, message, msgID);
DirectoryServer.sendAlertNotification(this,
ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
- return;
- }
- }
-
- // Read the contents of the current configuration file and put them into the
- // archive.
- try
- {
- FileInputStream inputStream = new FileInputStream(configFile);
-
- outputStream.putNextEntry(new ZipEntry(runningArchiveName));
-
- int bytesRead = inputStream.read(buffer);
- while (bytesRead > 0)
- {
- outputStream.write(buffer, 0, bytesRead);
- bytesRead = inputStream.read(buffer);
+ break writeConfigArchive;
}
- outputStream.closeEntry();
- inputStream.close();
- }
- catch (Exception e)
- {
- assert debugException(CLASS_NAME, "writeUpdatedConfig", e);
- int msgID = MSGID_CONFIG_FILE_WRITE_CANNOT_COPY_CURRENT_CONFIG;
- String message = getMessage(msgID, String.valueOf(tempArchive),
- String.valueOf(configFile),
- stackTraceToSingleLineString(e));
-
- logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.sendAlertNotification(this,
- ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
- return;
- }
-
-
- // Close the temporary archive, delete the existing archive, and replace it
- // with the temporary version.
- try
- {
- outputStream.close();
-
- if (archiveFile.exists())
+ // Copy the current configuration to the new configuration file.
+ byte[] buffer = new byte[8192];
+ FileInputStream inputStream = null;
+ GZIPOutputStream outputStream = null;
+ try
{
- archiveFile.delete();
+ inputStream = new FileInputStream(configFile);
+ outputStream = new GZIPOutputStream(new FileOutputStream(archiveFile));
+
+ int bytesRead = inputStream.read(buffer);
+ while (bytesRead > 0)
+ {
+ outputStream.write(buffer, 0, bytesRead);
+ bytesRead = inputStream.read(buffer);
+ }
}
-
- File tempArchiveFile = new File(tempArchive);
- if (! tempArchiveFile.renameTo(archiveFile))
+ catch (Exception e)
{
- int msgID = MSGID_CONFIG_FILE_WRITE_CANNOT_RENAME_TEMP_ARCHIVE;
- String message = getMessage(msgID, String.valueOf(tempArchive),
- String.valueOf(archiveName));
+ assert debugException(CLASS_NAME, "writeUpdatedConfig", e);
- logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
+ int msgID = MSGID_CONFIG_FILE_CANNOT_WRITE_CONFIG_ARCHIVE;
+ String message = getMessage(msgID, stackTraceToSingleLineString(e));
+
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_ERROR, message, msgID);
DirectoryServer.sendAlertNotification(this,
ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
- return;
+
+ break writeConfigArchive;
}
- }
- catch (Exception e)
- {
- assert debugException(CLASS_NAME, "writeUpdatedConfig", e);
+ finally
+ {
+ try
+ {
+ inputStream.close();
+ } catch (Exception e) {}
- int msgID = MSGID_CONFIG_FILE_WRITE_CANNOT_REPLACE_ARCHIVE;
- String message = getMessage(msgID, String.valueOf(archiveName),
- String.valueOf(tempArchive),
- stackTraceToSingleLineString(e));
-
- logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.sendAlertNotification(this,
- ALERT_TYPE_CANNOT_WRITE_CONFIGURATION, msgID, message);
- return;
+ try
+ {
+ outputStream.close();
+ } catch (Exception e) {}
+ }
}
@@ -1772,6 +1726,7 @@
// Delete the previous version of the configuration and rename the new one.
try
{
+ File f = new File(configFile);
f.delete();
new File(tempConfig).renameTo(f);
}
@@ -2295,43 +2250,46 @@
}
- // If we have a zip file with archived forms of previous configurations,
- // then add it as well.
+ // If an archive directory exists, then add its contents as well.
try
{
- File archivedConfigsFile = new File(new File(configFile).getParent() +
- File.separator + CONFIG_ARCHIVE_NAME);
- if (archivedConfigsFile.exists())
+ File archiveDirectory = new File(new File(configFile).getParent(),
+ CONFIG_ARCHIVE_DIR_NAME);
+ if (archiveDirectory.exists())
{
- ZipEntry zipEntry = new ZipEntry(archivedConfigsFile.getName());
- zipStream.putNextEntry(zipEntry);
-
- inputStream = new FileInputStream(archivedConfigsFile);
- while (true)
+ for (File archiveFile : archiveDirectory.listFiles())
{
- int bytesRead = inputStream.read(buffer);
- if (bytesRead < 0)
+ ZipEntry zipEntry = new ZipEntry(CONFIG_ARCHIVE_DIR_NAME +
+ File.separator +
+ archiveFile.getName());
+ zipStream.putNextEntry(zipEntry);
+ inputStream = new FileInputStream(archiveFile);
+ while (true)
{
- break;
+ int bytesRead = inputStream.read(buffer);
+ if (bytesRead < 0)
+ {
+ break;
+ }
+
+ if (hash)
+ {
+ if (signHash)
+ {
+ mac.update(buffer, 0, bytesRead);
+ }
+ else
+ {
+ digest.update(buffer, 0, bytesRead);
+ }
+ }
+
+ zipStream.write(buffer, 0, bytesRead);
}
- if (hash)
- {
- if (signHash)
- {
- mac.update(buffer, 0, bytesRead);
- }
- else
- {
- digest.update(buffer, 0, bytesRead);
- }
- }
-
- zipStream.write(buffer, 0, bytesRead);
+ inputStream.close();
+ zipStream.closeEntry();
}
-
- inputStream.close();
- zipStream.closeEntry();
}
}
catch (Exception e)
@@ -2690,11 +2648,12 @@
configBackupDir.mkdirs();
moveFile(configFile, configBackupDir);
- File archivedConfigsFile = new File(configDirPath + File.separator +
- CONFIG_ARCHIVE_NAME);
- if (archivedConfigsFile.exists())
+ File archiveDirectory = new File(configDir, CONFIG_ARCHIVE_DIR_NAME);
+ if (archiveDirectory.exists())
{
- moveFile(archivedConfigsFile, configBackupDir);
+ File archiveBackupPath = new File(configBackupDir,
+ CONFIG_ARCHIVE_DIR_NAME);
+ archiveDirectory.renameTo(archiveBackupPath);
}
}
}
@@ -2800,10 +2759,17 @@
OutputStream outputStream = null;
if (! verifyOnly)
{
- String filePath = configDirPath + File.separator + fileName;
+ File restoreFile = new File(configDirPath + File.separator + fileName);
+ File parentDir = restoreFile.getParentFile();
+
try
{
- outputStream = new FileOutputStream(filePath);
+ if (! parentDir.exists())
+ {
+ parentDir.mkdirs();
+ }
+
+ outputStream = new FileOutputStream(restoreFile);
}
catch (Exception e)
{
@@ -2817,7 +2783,8 @@
}
int msgID = MSGID_CONFIG_RESTORE_CANNOT_CREATE_FILE;
- String message = getMessage(msgID, backupID, filePath,
+ String message = getMessage(msgID, backupID,
+ restoreFile.getAbsolutePath(),
stackTraceToSingleLineString(e));
throw new DirectoryException(
DirectoryServer.getServerErrorResultCode(), message,
--
Gitblit v1.10.0