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 ) );
>
>
>