From dbc982944cd13543eaa810c6eb0b78a7c2524d86 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 17 Jun 2014 13:40:54 +0000
Subject: [PATCH] OPENDJ-1449 : File-based changelog should handle partially written record left over from a previous failure CR-3768
---
opends/src/server/org/opends/server/replication/server/changelog/file/LogFile.java | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 49 insertions(+), 1 deletions(-)
diff --git a/opends/src/server/org/opends/server/replication/server/changelog/file/LogFile.java b/opends/src/server/org/opends/server/replication/server/changelog/file/LogFile.java
index b27c78e..3b91bfa 100644
--- a/opends/src/server/org/opends/server/replication/server/changelog/file/LogFile.java
+++ b/opends/src/server/org/opends/server/replication/server/changelog/file/LogFile.java
@@ -26,6 +26,7 @@
package org.opends.server.replication.server.changelog.file;
import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import java.io.BufferedWriter;
@@ -33,6 +34,7 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.RandomAccessFile;
import org.forgerock.util.Reject;
import org.opends.messages.Message;
@@ -103,7 +105,15 @@
this.isWriteEnabled = isWriteEnabled;
createLogFileIfNotExists();
- writer = isWriteEnabled ? BlockLogWriter.newWriter(new LogWriter(logfile), parser) : null;
+ if (isWriteEnabled)
+ {
+ ensureLogFileIsValid(parser);
+ writer = BlockLogWriter.newWriter(new LogWriter(logfile), parser);
+ }
+ else
+ {
+ writer = null;
+ }
readerPool = new LogReaderPool<K, V>(logfile, parser);
}
@@ -184,6 +194,44 @@
}
/**
+ * Ensure that log file is not corrupted, by checking it is valid and cleaning
+ * the end of file if necessary, to remove a partially written record.
+ * <p>
+ * If log file is cleaned to remove a partially written record, then a message
+ * is logged for information.
+ *
+ * @throws ChangelogException
+ * If an error occurs or if log file is corrupted and can't be
+ * cleaned
+ */
+ private void ensureLogFileIsValid(final RecordParser<K, V> parser) throws ChangelogException
+ {
+ BlockLogReader<K, V> reader = null;
+ try
+ {
+ final RandomAccessFile readerWriter = new RandomAccessFile(logfile, "rws");
+ reader = BlockLogReader.newReader(logfile, readerWriter, parser) ;
+ final long lastValidPosition = reader.checkLogIsValid();
+ if (lastValidPosition != -1)
+ {
+ // truncate the file to point where last valid record has been read
+ readerWriter.setLength(lastValidPosition);
+ logError(INFO_CHANGELOG_LOG_FILE_RECOVERED.get(logfile.getPath()));
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ChangelogException(ERR_CHANGELOG_UNABLE_TO_RECOVER_LOG_FILE.get(
+ logfile.getPath(),
+ StaticUtils.stackTraceToSingleLineString(e)));
+ }
+ finally
+ {
+ StaticUtils.close(reader);
+ }
+ }
+
+ /**
* Add the provided record at the end of this log.
* <p>
* In order to ensure that record is written out of buffers and persisted
--
Gitblit v1.10.0