You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2011/10/27 11:24:23 UTC
svn commit: r1189688 - in /directory/apacheds/branches/apacheds-txns:
core-api/src/main/java/org/apache/directory/server/core/log/
core/src/main/java/org/apache/directory/server/core/log/
Author: elecharny
Date: Thu Oct 27 09:24:23 2011
New Revision: 1189688
URL: http://svn.apache.org/viewvc?rev=1189688&view=rev
Log:
o Added a Log.begingScan() method with no argument
o Added a checksum computation for userRecirds
o Renamed LogScanner to LogScannerInternal
o Made fields private
o Removed the LogScanner.init() method, used the constructor instead
o Added some Javadoc
o Added some comments
Modified:
directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java
directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java
directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java
directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java
directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java
directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java
directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java
Modified: directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java Thu Oct 27 09:24:23 2011
@@ -32,7 +32,7 @@ public interface Log
*
* @param logFilepath log file path
* @param suffix suffix for log file.
- * @param logBufferSize size of buffer that will hold unflushed log changes. Specifigy zero if no buffering is desired
+ * @param logBufferSize size of buffer that will hold unflushed log changes. Specify zero if no buffering is desired
* @param logFileSize A soft limit on the log file size
* @throws IOException
* @throws InvalidLogException
@@ -55,12 +55,20 @@ public interface Log
* Starts a scan in the logs starting from the given log position
*
* @param startPoint starting position of the scan.
- * @return
+ * @return A scanner to read the logs one by one
*/
LogScanner beginScan( LogAnchor startPoint );
/**
+ * Starts a scan in the logs starting from the beginning of the log file
+ *
+ * @return A scanner to read the logs one by one
+ */
+ LogScanner beginScan();
+
+
+ /**
* Advances the min needed position in the logs. Logging subsystem uses this
* information to get rid of unneeded
*
Modified: directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java Thu Oct 27 09:24:23 2011
@@ -22,6 +22,10 @@ package org.apache.directory.server.core
import java.io.IOException;
/**
+ * A utility class used to scan a Log file. We can only rea records forward,
+ * there is no way we can go backward. In order to start to read logs from
+ * a given position, the user must have set this position when requesting
+ * for a LogScanner (@see Log#beginScan(LogAnchor))
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@@ -32,12 +36,12 @@ public interface LogScanner
* and returns a reference to it. Returned array can be overwritten
* after the next call to getNextRecord()
*
- * @param log record to be filled in by
+ * @param logRecord record to be filled in by
* @return true if there is a next record
- * throws IOException
- * throws InvalidLogException thrown if the log content is invalid
+ * @throws IOException If we had some I/O issue
+ * @throws InvalidLogException thrown if the log content is invalid
*/
- boolean getNextRecord(UserLogRecord logRecord) throws IOException, InvalidLogException;
+ boolean getNextRecord( UserLogRecord logRecord ) throws IOException, InvalidLogException;
/**
@@ -47,6 +51,7 @@ public interface LogScanner
*/
long getLastGoodFileNumber();
+
/**
* Returns the last successfully read log file number
*
@@ -54,6 +59,7 @@ public interface LogScanner
*/
long getLastGoodOffset();
+
/**
* Closes the scanner and releases any
* resources.
Modified: directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java (original)
+++ directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java Thu Oct 27 09:24:23 2011
@@ -26,8 +26,6 @@ package org.apache.directory.server.core
*/
public class UserLogRecord
{
- private final static int INITIAL_SIZE = 1024;
-
/** array used to hold user log records */
private byte[] recordHolder;
@@ -37,6 +35,14 @@ public class UserLogRecord
/** Position of the log record in the log */
private LogAnchor logAnchor = new LogAnchor();
+
+ /**
+ * Store some data into the record. The buffer may be bigger than the
+ * data it contains, the length gives the real size of the stored data.
+ *
+ * @param data The buffer containing the data
+ * @param length The length of valid data in the buffer
+ */
public void setData( byte[] data, int length )
{
this.recordHolder = data;
@@ -44,18 +50,27 @@ public class UserLogRecord
}
+ /**
+ * @return The stored buffer, containing the data
+ */
public byte[] getDataBuffer()
{
return recordHolder;
}
+ /**
+ * @return The data length
+ */
public int getDataLength()
{
return length;
}
+ /**
+ * @return The position in the buffer
+ */
public LogAnchor getLogAnchor()
{
return logAnchor;
Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java (original)
+++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java Thu Oct 27 09:24:23 2011
@@ -65,8 +65,19 @@ public class DefaultLog implements Log
*/
public LogScanner beginScan( LogAnchor startPoint )
{
- LogScannerInternal logScanner = new DefaultLogScanner();
- logScanner.init( startPoint, logFileManager );
+ LogScanner logScanner = new DefaultLogScanner( startPoint, logFileManager );
+
+ return logScanner;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public LogScanner beginScan()
+ {
+ LogAnchor startPoint = new LogAnchor();
+ LogScanner logScanner = new DefaultLogScanner( startPoint, logFileManager );
return logScanner;
}
Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java (original)
+++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java Thu Oct 27 09:24:23 2011
@@ -23,14 +23,18 @@ import java.io.IOException;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.nio.ByteBuffer;
+import java.util.zip.Adler32;
+import java.util.zip.Checksum;
+import org.apache.directory.server.core.log.LogFileManager.LogFileReader;
import org.apache.directory.server.i18n.I18n;
/**
+ * An implementation of a LogScanner.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public class DefaultLogScanner implements LogScannerInternal
+public class DefaultLogScanner implements LogScanner
{
/** LSN of the last successfully read log record */
private long prevLSN = LogAnchor.UNKNOWN_LSN;
@@ -48,27 +52,30 @@ public class DefaultLogScanner implement
private long lastReadLSN = LogAnchor.UNKNOWN_LSN;
/** Current log file pointer to read from */
- LogFileManager.LogFileReader currentLogFile;
+ private LogFileManager.LogFileReader currentLogFile;
/** True if scanner is closed */
- boolean closed = false;
+ private boolean closed = false;
/** True if scanner hit invalid content. No more reads will be done after invalid log content is hit */
- boolean invalidLog = false;
+ private boolean invalidLog = false;
/** log file manager used to open files for reading */
- LogFileManager logFileManager;
-
- /** Buffer used to read log file markers */
- byte markerBuffer[] = new byte[LogFileRecords.MAX_MARKER_SIZE];
+ private LogFileManager logFileManager;
/** ByteBuffer wrapper for the marker buffer */
- ByteBuffer markerHead = ByteBuffer.wrap( markerBuffer );
-
+ private ByteBuffer markerHead = ByteBuffer.allocate( LogFileRecords.MAX_MARKER_SIZE );
+
+ /** The Checksum used */
+ private Checksum checksum = new Adler32();
+
/**
- * {@inheritDoc}
+ * Creates a new instance of a LogScanner.
+ *
+ * @param startingLogAnchor The starting position in the Log files
+ * @param logFileManager The underlying log file manager
*/
- public void init( LogAnchor startingLogAnchor, LogFileManager logFileManager )
+ public DefaultLogScanner( LogAnchor startingLogAnchor, LogFileManager logFileManager )
{
this.startingLogAnchor.resetLogAnchor( startingLogAnchor );
this.logFileManager = logFileManager;
@@ -96,6 +103,7 @@ public class DefaultLogScanner implement
{
if ( currentLogFile == null )
{
+ // We haven't yet opened a LogFile. Let's do it right away
long startingOffset = startingLogAnchor.getLogFileOffset();
// Read and verify header
@@ -115,6 +123,8 @@ public class DefaultLogScanner implement
}
prevLogFileOffset = Math.max( startingOffset, currentLogFile.getLength() );
+
+ // Move to the beginning of the data we want to read.
currentLogFile.seek( startingOffset );
}
@@ -132,14 +142,14 @@ public class DefaultLogScanner implement
}
else if ( fileOffset == fileLength )
{
- // Switch to next file.. This reads and verifies the header of the new file
+ // Switch to next file. This reads and verifies the header of the new file
long nextLogFileNumber = currentLogFile.logFileNumber() + 1;
currentLogFile.close();
currentLogFile = readFileHeader( nextLogFileNumber );
if ( currentLogFile == null )
{
- return false; // Done.. End of log stream
+ return false; // Done. End of log stream
}
}
else
@@ -163,11 +173,12 @@ public class DefaultLogScanner implement
}
}
- // Read and verify user block
+ // Read and verify the user block
readLogRecord( logRecord, recordLength - ( LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE ));
// Read and verify footer
- readRecordFooter();
+ checksum.update( logRecord.getDataBuffer(), 0, logRecord.getDataLength() );
+ readRecordFooter( (int)checksum.getValue() );
// If we are here, then we successfully read the log record.
// Set the read record's position, uptate last read good location
@@ -247,36 +258,17 @@ public class DefaultLogScanner implement
private int readRecordHeader() throws IOException, InvalidLogException, EOFException
{
- boolean invalid = false;
-
markerHead.rewind();
- currentLogFile.read( markerBuffer, 0, LogFileRecords.RECORD_HEADER_SIZE );
+ currentLogFile.read( markerHead.array(), 0, LogFileRecords.RECORD_HEADER_SIZE );
int magicNumber = markerHead.getInt();
int length = markerHead.getInt();
long lsn = markerHead.getLong();
long checksum = markerHead.getLong();
- if ( magicNumber != LogFileRecords.RECORD_HEADER_MAGIC_NUMBER )
- {
- invalid = true;
- }
-
- if ( length <= ( LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE ) )
- {
- invalid = true;
- }
-
- if ( lsn < prevLSN )
- {
- invalid = true;
- }
-
- if ( checksum != ( lsn ^ length ) )
- {
- invalid = true;
- }
-
- if ( invalid == true )
+ if ( ( magicNumber != LogFileRecords.RECORD_HEADER_MAGIC_NUMBER ) ||
+ ( length <= ( LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE ) ) ||
+ ( lsn < prevLSN ) ||
+ ( checksum != ( lsn ^ length ) ) )
{
markScanInvalid( null );
}
@@ -288,52 +280,60 @@ public class DefaultLogScanner implement
}
- private void readRecordFooter() throws IOException, InvalidLogException, EOFException
+ private void readRecordFooter( int expectedChecksum ) throws IOException, InvalidLogException, EOFException
{
- boolean invalid = false;
-
markerHead.rewind();
- currentLogFile.read( markerBuffer, 0, LogFileRecords.RECORD_FOOTER_SIZE );
+ currentLogFile.read( markerHead.array(), 0, LogFileRecords.RECORD_FOOTER_SIZE );
+
+ // The checksum
int checksum = markerHead.getInt();
- int magicNumber = markerHead.getInt();
-
- if ( magicNumber != LogFileRecords.RECORD_FOOTER_MAGIC_NUMBER )
- {
- invalid = true;
- }
- // TODO compute checksum
+ // The magicNumber
+ int magicNumber = markerHead.getInt();
- if ( invalid == true )
+
+ if ( ( magicNumber != LogFileRecords.RECORD_FOOTER_MAGIC_NUMBER ) ||
+ ( expectedChecksum != checksum ) )
{
markScanInvalid( null );
}
}
+ /**
+ * Read the data from the LogFile, excludinhg the header and footer.
+ */
private void readLogRecord( UserLogRecord userRecord, int length ) throws IOException, EOFException
{
byte dataBuffer[] = userRecord.getDataBuffer();
- if ( dataBuffer == null || dataBuffer.length < length )
+ if ( ( dataBuffer == null ) || ( dataBuffer.length < length ) )
{
// Allocate a larger buffer
dataBuffer = new byte[length];
}
currentLogFile.read( dataBuffer, 0, length );
+
+ // The size we read can be different from the bufer size, if we reused the
+ // buffer from a previous read.
userRecord.setData( dataBuffer, length );
}
- private LogFileManager.LogFileReader readFileHeader( long logFileNumber ) throws IOException, InvalidLogException, EOFException
+ /**
+ * Read the file header. It's a 12 bytes array, containing the file number (a long, on 8 bytes)
+ * and the magic number (on 4 bytes).
+ */
+ private LogFileReader readFileHeader( long logFileNumber ) throws IOException, InvalidLogException, EOFException
{
- boolean invalid = false;
- LogFileManager.LogFileReader logFile;
-
+ LogFileReader logFileReader;
+
+
+ // Get a reader on the logFile
try
{
- logFile = logFileManager.getReaderForLogFile( logFileNumber );
+ logFileReader = logFileManager.getReaderForLogFile( logFileNumber );
}
catch ( FileNotFoundException e )
{
@@ -342,32 +342,28 @@ public class DefaultLogScanner implement
// File exists
prevLogFileNumber = logFileNumber;
- prevLogFileOffset = 0;
markerHead.rewind();
- logFile.read( markerBuffer, 0, LogFileRecords.LOG_FILE_HEADER_SIZE );
+
+ // Read the Header
+ logFileReader.read( markerHead.array(), 0, LogFileRecords.LOG_FILE_HEADER_SIZE );
+ prevLogFileOffset = LogFileRecords.LOG_FILE_HEADER_SIZE;
+
+ // The file number
long persistedLogFileNumber = markerHead.getLong();
+
+ // The magic number
int magicNumber = markerHead.getInt();
- if ( persistedLogFileNumber != logFileNumber )
- {
- invalid = true;
- }
-
- if ( magicNumber != LogFileRecords.LOG_FILE_HEADER_MAGIC_NUMBER )
- {
- invalid = true;
- }
-
-
- if ( invalid == true )
+ // Check both values
+ if ( ( persistedLogFileNumber != logFileNumber ) ||
+ ( magicNumber != LogFileRecords.LOG_FILE_HEADER_MAGIC_NUMBER ) )
{
markScanInvalid( null );
}
- // Everything is fine, advance good file offset and return
- prevLogFileOffset = LogFileRecords.LOG_FILE_HEADER_SIZE;
- return logFile;
+ // Everything is fine, return
+ return logFileReader;
}
Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java (original)
+++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java Thu Oct 27 09:24:23 2011
@@ -25,10 +25,13 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.zip.Adler32;
+import java.util.zip.Checksum;
import java.io.IOException;
+import org.apache.directory.server.core.log.LogFileManager.LogFileWriter;
import org.apache.directory.server.i18n.I18n;
/**
@@ -67,24 +70,27 @@ import org.apache.directory.server.i18n.
private LogFileManager.LogFileWriter currentLogFile;
/** Log manager */
- LogManager logManager;
+ private LogManager logManager;
/** Size of data appended to the currentLogFile so far */
- long appendedSize;
+ private long appendedSize;
/** Sof limit on the log file size */
- long targetLogFileSize;
+ private long targetLogFileSize;
/** If logging cannot succeed, then loggingFailed is set to true and further logging is prevented */
- boolean logFailed;
-
+ private boolean logFailed;
+
+ /** The Checksum used */
+ private Checksum checksum = new Adler32();
+
/**
* TODO : doco
* @param logManager
* @param logMemoryBufferSize
* @param logFileSize
*/
- public LogFlushManager(LogManager logManager, int logMemoryBufferSize, long logFileSize )
+ public LogFlushManager( LogManager logManager, int logMemoryBufferSize, long logFileSize )
{
if ( ( logMemoryBufferSize < 0 ) || ( logFileSize < 0 ) )
{
@@ -108,7 +114,7 @@ import org.apache.directory.server.i18n.
* @throws IOException
* @throws InvalidLogException
*/
- public void append(UserLogRecord userRecord, boolean sync ) throws IOException, InvalidLogException
+ public void append( UserLogRecord userRecord, boolean sync ) throws IOException, InvalidLogException
{
long lsn = LogAnchor.UNKNOWN_LSN;
boolean appendedRecord = false;
@@ -118,6 +124,7 @@ import org.apache.directory.server.i18n.
int recordSize = LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE + length;
+ // The addition of a record is done in a protected section
appendLock.lock();
if ( logFailed )
@@ -136,7 +143,9 @@ import org.apache.directory.server.i18n.
currentLogFile = logManager.switchToNextLogFile( null );
appendedSize = currentLogFile.getLength();
}
-
+
+ // If we try to store more data that what can be hold by the current file,
+ // we have to switch to the next file
if ( appendedSize > targetLogFileSize )
{
// Make sure everything outstanding goes to the current log file
@@ -162,9 +171,16 @@ import org.apache.directory.server.i18n.
{
if ( writeHead.remaining() >= recordSize )
{
+ // Write the header
writeHeader( writeHead, recordSize, lsn );
+
+ // Write the data
writeHead.put( userBuffer, 0, length );
- writeFooter( writeHead, 0 );
+
+ // Compute the checksum and write the footer
+ checksum.update( userBuffer, 0, length );
+ writeFooter( writeHead, (int)checksum.getValue() );
+
appendedRecord = true;
}
else // ( writeHead.remaining() < recordSize )
@@ -190,9 +206,16 @@ import org.apache.directory.server.i18n.
if ( ( readHeadPosition - writeHead.position() ) > recordSize )
{
+ // Write the header
writeHeader( writeHead, recordSize, lsn );
+
+ // Write the data
writeHead.put( userBuffer, 0, length );
- writeFooter( writeHead, 0 );
+
+ // Compute the checksum and write the footer
+ checksum.update( userBuffer, 0, length );
+ writeFooter( writeHead, (int)checksum.getValue() );
+
appendedRecord = true;
}
else
@@ -203,7 +226,7 @@ import org.apache.directory.server.i18n.
}
}
else
- {
+ {
flush( lsn, userBuffer, 0, length, true );
}
@@ -293,7 +316,7 @@ import org.apache.directory.server.i18n.
{
flushLock.unlock();
return;
- }
+ }
if ( flushStatus.flushInProgress == false )
{
@@ -522,35 +545,40 @@ import org.apache.directory.server.i18n.
* Used to group the memory buffer data together
*/
private static class LogBuffer
- {
+ {
/** In memory buffer */
- byte buffer[];
-
+ private byte buffer[];
+
/** Used to scan the buffer while reading it to flush */
- ByteBuffer readHead;
+ private ByteBuffer readHead;
/** Advanced as readHead flushes data */
- int readHeadPosition;
+ private int readHeadPosition;
- /** Rewind count of readHead..used to avoid overwriting nonflushed data */
- AtomicInteger readHeadRewindCount;
+ /** Rewind count of readHead. Used to avoid overwriting non flushed data */
+ private AtomicInteger readHeadRewindCount;
/** Used to scan the buffer while appending records into it */
- ByteBuffer writeHead;
+ private ByteBuffer writeHead;
- /** Rewind count of writeHead..used to avoid overwriting nonflushed data */
- int writeHeadRewindCount;
+ /** Rewind count of writeHead. used to avoid overwriting non flushed data */
+ private int writeHeadRewindCount;
/** Used to mark records that should be skipped at the end of the log buffer */
- final static int SKIP_RECORD_LENGTH = -1;
+ private final static int SKIP_RECORD_LENGTH = -1;
/** Header footer buffer used when writing user buffers directly */
- byte headerFooterBuffer[];
+ private byte headerFooterBuffer[];
/** Used to format header footer buffer */
- ByteBuffer headerFooterHead;
+ private ByteBuffer headerFooterHead;
- public LogBuffer( int bufferSize, LogFileManager.LogFileWriter currentLogFile )
+ /**
+ * Create a new instance of a LogBuffer
+ * @param bufferSize
+ * @param currentLogFile
+ */
+ private LogBuffer( int bufferSize, LogFileWriter currentLogFile )
{
buffer = new byte[bufferSize];
readHead = ByteBuffer.wrap( buffer );
Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java?rev=1189688&r1=1189687&r2=1189688&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java (original)
+++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java Thu Oct 27 09:24:23 2011
@@ -97,7 +97,7 @@ import org.apache.directory.server.i18n.
public void initLogManager() throws IOException, InvalidLogException
{
LogAnchor scanPoint = new LogAnchor();
- LogScannerInternal scanner;
+ LogScanner scanner;
UserLogRecord logRecord;
LogFileManager.LogFileReader reader;
@@ -124,8 +124,7 @@ import org.apache.directory.server.i18n.
scanPoint.resetLogAnchor( minLogAnchor );
logRecord = new UserLogRecord();
- scanner = new DefaultLogScanner();
- scanner.init( scanPoint, logFileManager );
+ scanner = new DefaultLogScanner( scanPoint, logFileManager );
try
{
@@ -435,7 +434,7 @@ import org.apache.directory.server.i18n.
/**
* Creates the next log file. If the log file already exists, then it is reformatted, that is,
- * its size is truncated to zero and file header is writtten again.
+ * its size is truncated to zero and file header is written again.
*
* @param reformatExistingFile log file already exists and should be formatted. If false, log file should not exist.
* @throws IOException
@@ -455,13 +454,7 @@ import org.apache.directory.server.i18n.
// Try to create the file.
boolean fileAlreadyExists = logFileManager.createLogFile( logFileNumber );
- if ( ( reformatExistingFile == false ) && ( fileAlreadyExists == true ) )
- {
- // Didnt expect the file to be around
- throw new InvalidLogException( I18n.err( I18n.ERR_750 ) );
- }
-
- if ( ( reformatExistingFile == true ) && ( fileAlreadyExists == false ) )
+ if ( reformatExistingFile != fileAlreadyExists )
{
// Didnt expect the file to be around
throw new InvalidLogException( I18n.err( I18n.ERR_750 ) );
Re: svn commit: r1189688 - in /directory/apacheds/branches/apacheds-txns:
core-api/src/main/java/org/apache/directory/server/core/log/ core/src/main/java/org/apache/directory/server/core/log/
Posted by Emmanuel Lecharny <el...@gmail.com>.
On 10/29/11 11:09 AM, Emmanuel Lécharny wrote:
> On 10/29/11 8:23 AM, Selcuk AYA wrote:
>> I am OK both ways. If you have time, please go ahead. Also you were
>> talking about a bug you hit during a test, please upload a test case
>> for it so that I can take a look.
>
> Will do.
I have committed a new test : testLogSmallBuffer. It produces the
following stackTrace ;
org.apache.directory.server.core.log.InvalidLogException: ERR_750 Log
content is invalid
at
org.apache.directory.server.core.log.DefaultLogScanner.markScanInvalid(DefaultLogScanner.java:384)
at
org.apache.directory.server.core.log.DefaultLogScanner.readRecordFooter(DefaultLogScanner.java:298)
at
org.apache.directory.server.core.log.DefaultLogScanner.getNextRecord(DefaultLogScanner.java:181)
at
org.apache.directory.server.core.log.LogTest.testLogSmallBuffer(LogTest.java:144)
...
--
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com
Re: svn commit: r1189688 - in /directory/apacheds/branches/apacheds-txns:
core-api/src/main/java/org/apache/directory/server/core/log/ core/src/main/java/org/apache/directory/server/core/log/
Posted by Emmanuel Lécharny <el...@apache.org>.
On 10/29/11 8:23 AM, Selcuk AYA wrote:
> On Fri, Oct 28, 2011 at 8:55 PM, Emmanuel Lecharny<el...@gmail.com> wrote:
>> On 10/28/11 9:46 AM, Selcuk AYA wrote:
>>> On Thu, Oct 27, 2011 at 12:24 PM,<el...@apache.org> wrote:
>>>> Author: elecharny
>>>> Date: Thu Oct 27 09:24:23 2011
>>>> New Revision: 1189688
>>>>
>>>> URL: http://svn.apache.org/viewvc?rev=1189688&view=rev
>>>> Log:
>>>> o Added a Log.begingScan() method with no argument
>>> log files are deleted as minneeded log file is advances. So this
>>> method should get a consistent copy of the min needed log file or min
>>> existing log file and should start scanning from there.
>> yeah, I realized that this afternoon as I was working on the code. Should I
>> fix the method ?
> I am OK both ways. If you have time, please go ahead. Also you were
> talking about a bug you hit during a test, please upload a test case
> for it so that I can take a look.
Will do.
--
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com
Re: svn commit: r1189688 - in /directory/apacheds/branches/apacheds-txns:
core-api/src/main/java/org/apache/directory/server/core/log/ core/src/main/java/org/apache/directory/server/core/log/
Posted by Selcuk AYA <ay...@gmail.com>.
On Fri, Oct 28, 2011 at 8:55 PM, Emmanuel Lecharny <el...@gmail.com> wrote:
> On 10/28/11 9:46 AM, Selcuk AYA wrote:
>>
>> On Thu, Oct 27, 2011 at 12:24 PM,<el...@apache.org> wrote:
>>>
>>> Author: elecharny
>>> Date: Thu Oct 27 09:24:23 2011
>>> New Revision: 1189688
>>>
>>> URL: http://svn.apache.org/viewvc?rev=1189688&view=rev
>>> Log:
>>> o Added a Log.begingScan() method with no argument
>>
>> log files are deleted as minneeded log file is advances. So this
>> method should get a consistent copy of the min needed log file or min
>> existing log file and should start scanning from there.
>
> yeah, I realized that this afternoon as I was working on the code. Should I
> fix the method ?
I am OK both ways. If you have time, please go ahead. Also you were
talking about a bug you hit during a test, please upload a test case
for it so that I can take a look.
>>
>>> o Renamed LogScanner to LogScannerInternal
>>> o Made fields private
>>
>> I think it is unnecessary to make internal private class fields
>> private. As I mentioned before, I use these little inner classes to
>> group data together and I access them directly.
>
> This is just a protection. Later, if you make this inner class a plain
> class, you will have to make the field private.
>
>
> --
> Regards,
> Cordialement,
> Emmanuel Lécharny
> www.iktek.com
>
>
regards,
Selcuk
Re: svn commit: r1189688 - in /directory/apacheds/branches/apacheds-txns:
core-api/src/main/java/org/apache/directory/server/core/log/ core/src/main/java/org/apache/directory/server/core/log/
Posted by Emmanuel Lecharny <el...@gmail.com>.
On 10/28/11 9:46 AM, Selcuk AYA wrote:
> On Thu, Oct 27, 2011 at 12:24 PM,<el...@apache.org> wrote:
>> Author: elecharny
>> Date: Thu Oct 27 09:24:23 2011
>> New Revision: 1189688
>>
>> URL: http://svn.apache.org/viewvc?rev=1189688&view=rev
>> Log:
>> o Added a Log.begingScan() method with no argument
> log files are deleted as minneeded log file is advances. So this
> method should get a consistent copy of the min needed log file or min
> existing log file and should start scanning from there.
yeah, I realized that this afternoon as I was working on the code.
Should I fix the method ?
>
>> o Renamed LogScanner to LogScannerInternal
>> o Made fields private
> I think it is unnecessary to make internal private class fields
> private. As I mentioned before, I use these little inner classes to
> group data together and I access them directly.
This is just a protection. Later, if you make this inner class a plain
class, you will have to make the field private.
--
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com
Re: svn commit: r1189688 - in /directory/apacheds/branches/apacheds-txns:
core-api/src/main/java/org/apache/directory/server/core/log/ core/src/main/java/org/apache/directory/server/core/log/
Posted by Selcuk AYA <ay...@gmail.com>.
On Thu, Oct 27, 2011 at 12:24 PM, <el...@apache.org> wrote:
> Author: elecharny
> Date: Thu Oct 27 09:24:23 2011
> New Revision: 1189688
>
> URL: http://svn.apache.org/viewvc?rev=1189688&view=rev
> Log:
> o Added a Log.begingScan() method with no argument
log files are deleted as minneeded log file is advances. So this
method should get a consistent copy of the min needed log file or min
existing log file and should start scanning from there.
> o Added a checksum computation for userRecirds
thanks!
> o Renamed LogScanner to LogScannerInternal
> o Made fields private
I think it is unnecessary to make internal private class fields
private. As I mentioned before, I use these little inner classes to
group data together and I access them directly.
> o Removed the LogScanner.init() method, used the constructor instead
> o Added some Javadoc
> o Added some comments
>
> Modified:
> directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java
> directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java
> directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java
> directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java
> directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java
> directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java
> directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java
>
> Modified: directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/Log.java Thu Oct 27 09:24:23 2011
> @@ -32,7 +32,7 @@ public interface Log
> *
> * @param logFilepath log file path
> * @param suffix suffix for log file.
> - * @param logBufferSize size of buffer that will hold unflushed log changes. Specifigy zero if no buffering is desired
> + * @param logBufferSize size of buffer that will hold unflushed log changes. Specify zero if no buffering is desired
> * @param logFileSize A soft limit on the log file size
> * @throws IOException
> * @throws InvalidLogException
> @@ -55,12 +55,20 @@ public interface Log
> * Starts a scan in the logs starting from the given log position
> *
> * @param startPoint starting position of the scan.
> - * @return
> + * @return A scanner to read the logs one by one
> */
> LogScanner beginScan( LogAnchor startPoint );
>
>
> /**
> + * Starts a scan in the logs starting from the beginning of the log file
> + *
> + * @return A scanner to read the logs one by one
> + */
> + LogScanner beginScan();
> +
> +
> + /**
> * Advances the min needed position in the logs. Logging subsystem uses this
> * information to get rid of unneeded
> *
>
> Modified: directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/LogScanner.java Thu Oct 27 09:24:23 2011
> @@ -22,6 +22,10 @@ package org.apache.directory.server.core
> import java.io.IOException;
>
> /**
> + * A utility class used to scan a Log file. We can only rea records forward,
> + * there is no way we can go backward. In order to start to read logs from
> + * a given position, the user must have set this position when requesting
> + * for a LogScanner (@see Log#beginScan(LogAnchor))
> *
> * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
> */
> @@ -32,12 +36,12 @@ public interface LogScanner
> * and returns a reference to it. Returned array can be overwritten
> * after the next call to getNextRecord()
> *
> - * @param log record to be filled in by
> + * @param logRecord record to be filled in by
> * @return true if there is a next record
> - * throws IOException
> - * throws InvalidLogException thrown if the log content is invalid
> + * @throws IOException If we had some I/O issue
> + * @throws InvalidLogException thrown if the log content is invalid
> */
> - boolean getNextRecord(UserLogRecord logRecord) throws IOException, InvalidLogException;
> + boolean getNextRecord( UserLogRecord logRecord ) throws IOException, InvalidLogException;
>
>
> /**
> @@ -47,6 +51,7 @@ public interface LogScanner
> */
> long getLastGoodFileNumber();
>
> +
> /**
> * Returns the last successfully read log file number
> *
> @@ -54,6 +59,7 @@ public interface LogScanner
> */
> long getLastGoodOffset();
>
> +
> /**
> * Closes the scanner and releases any
> * resources.
>
> Modified: directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core-api/src/main/java/org/apache/directory/server/core/log/UserLogRecord.java Thu Oct 27 09:24:23 2011
> @@ -26,8 +26,6 @@ package org.apache.directory.server.core
> */
> public class UserLogRecord
> {
> - private final static int INITIAL_SIZE = 1024;
> -
> /** array used to hold user log records */
> private byte[] recordHolder;
>
> @@ -37,6 +35,14 @@ public class UserLogRecord
> /** Position of the log record in the log */
> private LogAnchor logAnchor = new LogAnchor();
>
> +
> + /**
> + * Store some data into the record. The buffer may be bigger than the
> + * data it contains, the length gives the real size of the stored data.
> + *
> + * @param data The buffer containing the data
> + * @param length The length of valid data in the buffer
> + */
> public void setData( byte[] data, int length )
> {
> this.recordHolder = data;
> @@ -44,18 +50,27 @@ public class UserLogRecord
> }
>
>
> + /**
> + * @return The stored buffer, containing the data
> + */
> public byte[] getDataBuffer()
> {
> return recordHolder;
> }
>
>
> + /**
> + * @return The data length
> + */
> public int getDataLength()
> {
> return length;
> }
>
>
> + /**
> + * @return The position in the buffer
> + */
> public LogAnchor getLogAnchor()
> {
> return logAnchor;
>
> Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLog.java Thu Oct 27 09:24:23 2011
> @@ -65,8 +65,19 @@ public class DefaultLog implements Log
> */
> public LogScanner beginScan( LogAnchor startPoint )
> {
> - LogScannerInternal logScanner = new DefaultLogScanner();
> - logScanner.init( startPoint, logFileManager );
> + LogScanner logScanner = new DefaultLogScanner( startPoint, logFileManager );
> +
> + return logScanner;
> + }
> +
> +
> + /**
> + * {@inheritDoc}
> + */
> + public LogScanner beginScan()
> + {
> + LogAnchor startPoint = new LogAnchor();
> + LogScanner logScanner = new DefaultLogScanner( startPoint, logFileManager );
>
> return logScanner;
> }
>
> Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/DefaultLogScanner.java Thu Oct 27 09:24:23 2011
> @@ -23,14 +23,18 @@ import java.io.IOException;
> import java.io.EOFException;
> import java.io.FileNotFoundException;
> import java.nio.ByteBuffer;
> +import java.util.zip.Adler32;
> +import java.util.zip.Checksum;
>
> +import org.apache.directory.server.core.log.LogFileManager.LogFileReader;
> import org.apache.directory.server.i18n.I18n;
>
> /**
> + * An implementation of a LogScanner.
> *
> * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
> */
> -public class DefaultLogScanner implements LogScannerInternal
> +public class DefaultLogScanner implements LogScanner
> {
> /** LSN of the last successfully read log record */
> private long prevLSN = LogAnchor.UNKNOWN_LSN;
> @@ -48,27 +52,30 @@ public class DefaultLogScanner implement
> private long lastReadLSN = LogAnchor.UNKNOWN_LSN;
>
> /** Current log file pointer to read from */
> - LogFileManager.LogFileReader currentLogFile;
> + private LogFileManager.LogFileReader currentLogFile;
>
> /** True if scanner is closed */
> - boolean closed = false;
> + private boolean closed = false;
>
> /** True if scanner hit invalid content. No more reads will be done after invalid log content is hit */
> - boolean invalidLog = false;
> + private boolean invalidLog = false;
>
> /** log file manager used to open files for reading */
> - LogFileManager logFileManager;
> -
> - /** Buffer used to read log file markers */
> - byte markerBuffer[] = new byte[LogFileRecords.MAX_MARKER_SIZE];
> + private LogFileManager logFileManager;
>
> /** ByteBuffer wrapper for the marker buffer */
> - ByteBuffer markerHead = ByteBuffer.wrap( markerBuffer );
> -
> + private ByteBuffer markerHead = ByteBuffer.allocate( LogFileRecords.MAX_MARKER_SIZE );
> +
> + /** The Checksum used */
> + private Checksum checksum = new Adler32();
> +
> /**
> - * {@inheritDoc}
> + * Creates a new instance of a LogScanner.
> + *
> + * @param startingLogAnchor The starting position in the Log files
> + * @param logFileManager The underlying log file manager
> */
> - public void init( LogAnchor startingLogAnchor, LogFileManager logFileManager )
> + public DefaultLogScanner( LogAnchor startingLogAnchor, LogFileManager logFileManager )
> {
> this.startingLogAnchor.resetLogAnchor( startingLogAnchor );
> this.logFileManager = logFileManager;
> @@ -96,6 +103,7 @@ public class DefaultLogScanner implement
> {
> if ( currentLogFile == null )
> {
> + // We haven't yet opened a LogFile. Let's do it right away
> long startingOffset = startingLogAnchor.getLogFileOffset();
>
> // Read and verify header
> @@ -115,6 +123,8 @@ public class DefaultLogScanner implement
> }
>
> prevLogFileOffset = Math.max( startingOffset, currentLogFile.getLength() );
> +
> + // Move to the beginning of the data we want to read.
> currentLogFile.seek( startingOffset );
> }
>
> @@ -132,14 +142,14 @@ public class DefaultLogScanner implement
> }
> else if ( fileOffset == fileLength )
> {
> - // Switch to next file.. This reads and verifies the header of the new file
> + // Switch to next file. This reads and verifies the header of the new file
> long nextLogFileNumber = currentLogFile.logFileNumber() + 1;
> currentLogFile.close();
> currentLogFile = readFileHeader( nextLogFileNumber );
>
> if ( currentLogFile == null )
> {
> - return false; // Done.. End of log stream
> + return false; // Done. End of log stream
> }
> }
> else
> @@ -163,11 +173,12 @@ public class DefaultLogScanner implement
> }
> }
>
> - // Read and verify user block
> + // Read and verify the user block
> readLogRecord( logRecord, recordLength - ( LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE ));
>
> // Read and verify footer
> - readRecordFooter();
> + checksum.update( logRecord.getDataBuffer(), 0, logRecord.getDataLength() );
> + readRecordFooter( (int)checksum.getValue() );
>
> // If we are here, then we successfully read the log record.
> // Set the read record's position, uptate last read good location
> @@ -247,36 +258,17 @@ public class DefaultLogScanner implement
>
> private int readRecordHeader() throws IOException, InvalidLogException, EOFException
> {
> - boolean invalid = false;
> -
> markerHead.rewind();
> - currentLogFile.read( markerBuffer, 0, LogFileRecords.RECORD_HEADER_SIZE );
> + currentLogFile.read( markerHead.array(), 0, LogFileRecords.RECORD_HEADER_SIZE );
> int magicNumber = markerHead.getInt();
> int length = markerHead.getInt();
> long lsn = markerHead.getLong();
> long checksum = markerHead.getLong();
>
> - if ( magicNumber != LogFileRecords.RECORD_HEADER_MAGIC_NUMBER )
> - {
> - invalid = true;
> - }
> -
> - if ( length <= ( LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE ) )
> - {
> - invalid = true;
> - }
> -
> - if ( lsn < prevLSN )
> - {
> - invalid = true;
> - }
> -
> - if ( checksum != ( lsn ^ length ) )
> - {
> - invalid = true;
> - }
> -
> - if ( invalid == true )
> + if ( ( magicNumber != LogFileRecords.RECORD_HEADER_MAGIC_NUMBER ) ||
> + ( length <= ( LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE ) ) ||
> + ( lsn < prevLSN ) ||
> + ( checksum != ( lsn ^ length ) ) )
> {
> markScanInvalid( null );
> }
> @@ -288,52 +280,60 @@ public class DefaultLogScanner implement
> }
>
>
> - private void readRecordFooter() throws IOException, InvalidLogException, EOFException
> + private void readRecordFooter( int expectedChecksum ) throws IOException, InvalidLogException, EOFException
> {
> - boolean invalid = false;
> -
> markerHead.rewind();
> - currentLogFile.read( markerBuffer, 0, LogFileRecords.RECORD_FOOTER_SIZE );
> + currentLogFile.read( markerHead.array(), 0, LogFileRecords.RECORD_FOOTER_SIZE );
> +
> + // The checksum
> int checksum = markerHead.getInt();
> - int magicNumber = markerHead.getInt();
> -
> - if ( magicNumber != LogFileRecords.RECORD_FOOTER_MAGIC_NUMBER )
> - {
> - invalid = true;
> - }
>
> - // TODO compute checksum
> + // The magicNumber
> + int magicNumber = markerHead.getInt();
>
> - if ( invalid == true )
> +
> + if ( ( magicNumber != LogFileRecords.RECORD_FOOTER_MAGIC_NUMBER ) ||
> + ( expectedChecksum != checksum ) )
> {
> markScanInvalid( null );
> }
> }
>
>
> + /**
> + * Read the data from the LogFile, excludinhg the header and footer.
> + */
> private void readLogRecord( UserLogRecord userRecord, int length ) throws IOException, EOFException
> {
> byte dataBuffer[] = userRecord.getDataBuffer();
>
> - if ( dataBuffer == null || dataBuffer.length < length )
> + if ( ( dataBuffer == null ) || ( dataBuffer.length < length ) )
> {
> // Allocate a larger buffer
> dataBuffer = new byte[length];
> }
>
> currentLogFile.read( dataBuffer, 0, length );
> +
> + // The size we read can be different from the bufer size, if we reused the
> + // buffer from a previous read.
> userRecord.setData( dataBuffer, length );
> }
>
>
> - private LogFileManager.LogFileReader readFileHeader( long logFileNumber ) throws IOException, InvalidLogException, EOFException
> + /**
> + * Read the file header. It's a 12 bytes array, containing the file number (a long, on 8 bytes)
> + * and the magic number (on 4 bytes).
> + */
> + private LogFileReader readFileHeader( long logFileNumber ) throws IOException, InvalidLogException, EOFException
> {
> - boolean invalid = false;
> - LogFileManager.LogFileReader logFile;
> -
> + LogFileReader logFileReader;
> +
> +
> + // Get a reader on the logFile
> try
> {
> - logFile = logFileManager.getReaderForLogFile( logFileNumber );
> + logFileReader = logFileManager.getReaderForLogFile( logFileNumber );
> }
> catch ( FileNotFoundException e )
> {
> @@ -342,32 +342,28 @@ public class DefaultLogScanner implement
>
> // File exists
> prevLogFileNumber = logFileNumber;
> - prevLogFileOffset = 0;
>
> markerHead.rewind();
> - logFile.read( markerBuffer, 0, LogFileRecords.LOG_FILE_HEADER_SIZE );
> +
> + // Read the Header
> + logFileReader.read( markerHead.array(), 0, LogFileRecords.LOG_FILE_HEADER_SIZE );
> + prevLogFileOffset = LogFileRecords.LOG_FILE_HEADER_SIZE;
> +
> + // The file number
> long persistedLogFileNumber = markerHead.getLong();
> +
> + // The magic number
> int magicNumber = markerHead.getInt();
>
> - if ( persistedLogFileNumber != logFileNumber )
> - {
> - invalid = true;
> - }
> -
> - if ( magicNumber != LogFileRecords.LOG_FILE_HEADER_MAGIC_NUMBER )
> - {
> - invalid = true;
> - }
> -
> -
> - if ( invalid == true )
> + // Check both values
> + if ( ( persistedLogFileNumber != logFileNumber ) ||
> + ( magicNumber != LogFileRecords.LOG_FILE_HEADER_MAGIC_NUMBER ) )
> {
> markScanInvalid( null );
> }
>
> - // Everything is fine, advance good file offset and return
> - prevLogFileOffset = LogFileRecords.LOG_FILE_HEADER_SIZE;
> - return logFile;
> + // Everything is fine, return
> + return logFileReader;
> }
>
>
>
> Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogFlushManager.java Thu Oct 27 09:24:23 2011
> @@ -25,10 +25,13 @@ import java.util.concurrent.locks.Lock;
> import java.util.concurrent.locks.ReentrantLock;
> import java.util.concurrent.locks.Condition;
> import java.util.concurrent.atomic.AtomicInteger;
> +import java.util.zip.Adler32;
> +import java.util.zip.Checksum;
>
>
> import java.io.IOException;
>
> +import org.apache.directory.server.core.log.LogFileManager.LogFileWriter;
> import org.apache.directory.server.i18n.I18n;
>
> /**
> @@ -67,24 +70,27 @@ import org.apache.directory.server.i18n.
> private LogFileManager.LogFileWriter currentLogFile;
>
> /** Log manager */
> - LogManager logManager;
> + private LogManager logManager;
>
> /** Size of data appended to the currentLogFile so far */
> - long appendedSize;
> + private long appendedSize;
>
> /** Sof limit on the log file size */
> - long targetLogFileSize;
> + private long targetLogFileSize;
>
> /** If logging cannot succeed, then loggingFailed is set to true and further logging is prevented */
> - boolean logFailed;
> -
> + private boolean logFailed;
> +
> + /** The Checksum used */
> + private Checksum checksum = new Adler32();
> +
> /**
> * TODO : doco
> * @param logManager
> * @param logMemoryBufferSize
> * @param logFileSize
> */
> - public LogFlushManager(LogManager logManager, int logMemoryBufferSize, long logFileSize )
> + public LogFlushManager( LogManager logManager, int logMemoryBufferSize, long logFileSize )
> {
> if ( ( logMemoryBufferSize < 0 ) || ( logFileSize < 0 ) )
> {
> @@ -108,7 +114,7 @@ import org.apache.directory.server.i18n.
> * @throws IOException
> * @throws InvalidLogException
> */
> - public void append(UserLogRecord userRecord, boolean sync ) throws IOException, InvalidLogException
> + public void append( UserLogRecord userRecord, boolean sync ) throws IOException, InvalidLogException
> {
> long lsn = LogAnchor.UNKNOWN_LSN;
> boolean appendedRecord = false;
> @@ -118,6 +124,7 @@ import org.apache.directory.server.i18n.
>
> int recordSize = LogFileRecords.RECORD_HEADER_SIZE + LogFileRecords.RECORD_FOOTER_SIZE + length;
>
> + // The addition of a record is done in a protected section
> appendLock.lock();
>
> if ( logFailed )
> @@ -136,7 +143,9 @@ import org.apache.directory.server.i18n.
> currentLogFile = logManager.switchToNextLogFile( null );
> appendedSize = currentLogFile.getLength();
> }
> -
> +
> + // If we try to store more data that what can be hold by the current file,
> + // we have to switch to the next file
> if ( appendedSize > targetLogFileSize )
> {
> // Make sure everything outstanding goes to the current log file
> @@ -162,9 +171,16 @@ import org.apache.directory.server.i18n.
> {
> if ( writeHead.remaining() >= recordSize )
> {
> + // Write the header
> writeHeader( writeHead, recordSize, lsn );
> +
> + // Write the data
> writeHead.put( userBuffer, 0, length );
> - writeFooter( writeHead, 0 );
> +
> + // Compute the checksum and write the footer
> + checksum.update( userBuffer, 0, length );
> + writeFooter( writeHead, (int)checksum.getValue() );
> +
> appendedRecord = true;
> }
> else // ( writeHead.remaining() < recordSize )
> @@ -190,9 +206,16 @@ import org.apache.directory.server.i18n.
>
> if ( ( readHeadPosition - writeHead.position() ) > recordSize )
> {
> + // Write the header
> writeHeader( writeHead, recordSize, lsn );
> +
> + // Write the data
> writeHead.put( userBuffer, 0, length );
> - writeFooter( writeHead, 0 );
> +
> + // Compute the checksum and write the footer
> + checksum.update( userBuffer, 0, length );
> + writeFooter( writeHead, (int)checksum.getValue() );
> +
> appendedRecord = true;
> }
> else
> @@ -203,7 +226,7 @@ import org.apache.directory.server.i18n.
> }
> }
> else
> - {
> + {
> flush( lsn, userBuffer, 0, length, true );
> }
>
> @@ -293,7 +316,7 @@ import org.apache.directory.server.i18n.
> {
> flushLock.unlock();
> return;
> - }
> + }
>
> if ( flushStatus.flushInProgress == false )
> {
> @@ -522,35 +545,40 @@ import org.apache.directory.server.i18n.
> * Used to group the memory buffer data together
> */
> private static class LogBuffer
> - {
> + {
> /** In memory buffer */
> - byte buffer[];
> -
> + private byte buffer[];
> +
> /** Used to scan the buffer while reading it to flush */
> - ByteBuffer readHead;
> + private ByteBuffer readHead;
>
> /** Advanced as readHead flushes data */
> - int readHeadPosition;
> + private int readHeadPosition;
>
> - /** Rewind count of readHead..used to avoid overwriting nonflushed data */
> - AtomicInteger readHeadRewindCount;
> + /** Rewind count of readHead. Used to avoid overwriting non flushed data */
> + private AtomicInteger readHeadRewindCount;
>
> /** Used to scan the buffer while appending records into it */
> - ByteBuffer writeHead;
> + private ByteBuffer writeHead;
>
> - /** Rewind count of writeHead..used to avoid overwriting nonflushed data */
> - int writeHeadRewindCount;
> + /** Rewind count of writeHead. used to avoid overwriting non flushed data */
> + private int writeHeadRewindCount;
>
> /** Used to mark records that should be skipped at the end of the log buffer */
> - final static int SKIP_RECORD_LENGTH = -1;
> + private final static int SKIP_RECORD_LENGTH = -1;
>
> /** Header footer buffer used when writing user buffers directly */
> - byte headerFooterBuffer[];
> + private byte headerFooterBuffer[];
>
> /** Used to format header footer buffer */
> - ByteBuffer headerFooterHead;
> + private ByteBuffer headerFooterHead;
>
> - public LogBuffer( int bufferSize, LogFileManager.LogFileWriter currentLogFile )
> + /**
> + * Create a new instance of a LogBuffer
> + * @param bufferSize
> + * @param currentLogFile
> + */
> + private LogBuffer( int bufferSize, LogFileWriter currentLogFile )
> {
> buffer = new byte[bufferSize];
> readHead = ByteBuffer.wrap( buffer );
>
> Modified: directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java
> URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java?rev=1189688&r1=1189687&r2=1189688&view=diff
> ==============================================================================
> --- directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java (original)
> +++ directory/apacheds/branches/apacheds-txns/core/src/main/java/org/apache/directory/server/core/log/LogManager.java Thu Oct 27 09:24:23 2011
> @@ -97,7 +97,7 @@ import org.apache.directory.server.i18n.
> public void initLogManager() throws IOException, InvalidLogException
> {
> LogAnchor scanPoint = new LogAnchor();
> - LogScannerInternal scanner;
> + LogScanner scanner;
> UserLogRecord logRecord;
> LogFileManager.LogFileReader reader;
>
> @@ -124,8 +124,7 @@ import org.apache.directory.server.i18n.
> scanPoint.resetLogAnchor( minLogAnchor );
>
> logRecord = new UserLogRecord();
> - scanner = new DefaultLogScanner();
> - scanner.init( scanPoint, logFileManager );
> + scanner = new DefaultLogScanner( scanPoint, logFileManager );
>
> try
> {
> @@ -435,7 +434,7 @@ import org.apache.directory.server.i18n.
>
> /**
> * Creates the next log file. If the log file already exists, then it is reformatted, that is,
> - * its size is truncated to zero and file header is writtten again.
> + * its size is truncated to zero and file header is written again.
> *
> * @param reformatExistingFile log file already exists and should be formatted. If false, log file should not exist.
> * @throws IOException
> @@ -455,13 +454,7 @@ import org.apache.directory.server.i18n.
> // Try to create the file.
> boolean fileAlreadyExists = logFileManager.createLogFile( logFileNumber );
>
> - if ( ( reformatExistingFile == false ) && ( fileAlreadyExists == true ) )
> - {
> - // Didnt expect the file to be around
> - throw new InvalidLogException( I18n.err( I18n.ERR_750 ) );
> - }
> -
> - if ( ( reformatExistingFile == true ) && ( fileAlreadyExists == false ) )
> + if ( reformatExistingFile != fileAlreadyExists )
> {
> // Didnt expect the file to be around
> throw new InvalidLogException( I18n.err( I18n.ERR_750 ) );
>
>
>