You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2010/09/19 12:13:15 UTC

svn commit: r998624 - /directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java

Author: kayyagari
Date: Sun Sep 19 10:13:15 2010
New Revision: 998624

URL: http://svn.apache.org/viewvc?rev=998624&view=rev
Log:
o added support for inserting LDIF entry in the middle of the other existing entries
o added entry's id to the  EntryOffset class 

Modified:
    directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java

Modified: directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java?rev=998624&r1=998623&r2=998624&view=diff
==============================================================================
--- directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java (original)
+++ directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java Sun Sep 19 10:13:15 2010
@@ -21,12 +21,15 @@
 package org.apache.directory.server.core.partition.ldif;
 
 
-import java.io.FileNotFoundException;
+import java.io.File;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.UUID;
 
 import javax.naming.InvalidNameException;
@@ -66,6 +69,9 @@ public class SingleFileLdifPartition ext
     /** the LDIF file holding the partition's data */
     private RandomAccessFile ldifFile;
 
+    /** a temporary file used for swapping contents while performing update operations */
+    private RandomAccessFile tempBufFile;
+
     /** offset map for entries in the ldif file */
     Map<Comparable, EntryOffset> offsetMap = new HashMap<Comparable, EntryOffset>();
 
@@ -88,8 +94,13 @@ public class SingleFileLdifPartition ext
         try
         {
             ldifFile = new RandomAccessFile( file, "rws" );
+
+            File tmpFile = File.createTempFile( "ldifpartition", ".buf" );
+            tmpFile.deleteOnExit();
+
+            tempBufFile = new RandomAccessFile( tmpFile.getAbsolutePath(), "rws" );
         }
-        catch ( FileNotFoundException e )
+        catch ( IOException e )
         {
             throw new RuntimeException( e );
         }
@@ -157,7 +168,11 @@ public class SingleFileLdifPartition ext
         {
             addMandatoryOpAt( contextEntry );
             store.add( contextEntry );
-            offsetMap.put( store.getEntryId( suffix ), new EntryOffset( curEnryStart, curEntryEnd ) );
+
+            Comparable id = store.getEntryId( suffix );
+            EntryOffset entryOffset = new EntryOffset( id, curEnryStart, curEntryEnd );
+
+            offsetMap.put( id, entryOffset );
         }
         else
         {
@@ -169,7 +184,8 @@ public class SingleFileLdifPartition ext
 
         while ( itr.hasNext() )
         {
-            EntryOffset offset = new EntryOffset( curEnryStart, curEntryEnd );
+            long tmpStart = curEnryStart;
+            long tmpEnd = curEntryEnd;
 
             ldifEntry = itr.next();
 
@@ -182,7 +198,11 @@ public class SingleFileLdifPartition ext
 
             addMandatoryOpAt( entry );
             store.add( entry );
-            offsetMap.put( store.getEntryId( entry.getDn() ), offset );
+
+            Comparable id = store.getEntryId( entry.getDn() );
+            EntryOffset offset = new EntryOffset( id, tmpStart, tmpEnd );
+
+            offsetMap.put( id, offset );
         }
 
         parser.close();
@@ -219,13 +239,13 @@ public class SingleFileLdifPartition ext
             // entry has a parent
             Long parentId = wrappedPartition.getEntryId( dn.getParent() );
             EntryOffset parentOffset = offsetMap.get( parentId );
-            if ( parentOffset.end == ldifFile.length() )
+            if ( parentOffset.getEnd() == ldifFile.length() )
             {
                 appendLdif( id, parentOffset, ldif );
             }
             else
             {
-                System.out.println( "====================implement insertion====================" );
+                insertLdif( id, parentOffset, ldif );
             }
         }
         catch ( IOException e )
@@ -271,61 +291,85 @@ public class SingleFileLdifPartition ext
 
 
     /**
-     * append data to the LDIF file
+     * inserts a given LDIF entry in the middle of the LDIF file
      *
-     * @param entryId
-     * @param parentOffset
-     * @param ldif
+     * @param entryId the entry's id
+     * @param parentOffset entry parent's offsets
+     * @param ldif the entry's ldif to be injected
      * @throws LdapException
      */
-    private void appendLdif( Comparable<Long> entryId, EntryOffset parentOffset, String ldif ) throws LdapException
+    private void insertLdif( Comparable<Long> entryId, EntryOffset parentOffset, String ldif ) throws LdapException
     {
+        if ( parentOffset == null )
+        {
+            throw new IllegalStateException( "parent offset is null" );
+        }
+
         try
         {
-            long pos = 0L;
+            FileChannel tmpBufChannel = tempBufFile.getChannel();
+            FileChannel mainChannel = ldifFile.getChannel();
 
-            if ( parentOffset != null )
-            {
-                pos = parentOffset.end;
-            }
+            // clear the buffer
+            tempBufFile.setLength( 0 );
 
-            ldifFile.seek( pos );
+            long count = ( ldifFile.length() - parentOffset.getEnd() );
 
-            ldifFile.write( StringTools.getBytesUtf8( ldif + "\n" ) );
+            mainChannel.transferTo( parentOffset.getEnd(), count, tmpBufChannel );
+            ldifFile.setLength( parentOffset.getEnd() );
 
-            offsetMap.put( entryId, new EntryOffset( pos, ldifFile.getFilePointer() ) );
+            Set<EntryOffset> belowParentOffsets = greaterThan( parentOffset );
+
+            EntryOffset entryOffset = appendLdif( entryId, parentOffset, ldif );
+
+            long diff = entryOffset.length();
+
+            for ( EntryOffset o : belowParentOffsets )
+            {
+                o.increaseOffsetsBy( diff );
+            }
+            
+            tmpBufChannel.transferTo( 0, tmpBufChannel.size(), mainChannel );
         }
         catch ( IOException e )
         {
             throw new LdapException( e );
         }
     }
-    
+
 
     /**
-     * a holder class for containing an entry's start and end offset positions
-     * in the LDIF file
+     * append data to the LDIF file
+     *
+     * @param entryId
+     * @param parentOffset
+     * @param ldif
+     * @throws LdapException
      */
-    private class EntryOffset
+    private EntryOffset appendLdif( Comparable<Long> entryId, EntryOffset parentOffset, String ldif )
+        throws LdapException
     {
-        /** starting position */
-        long start;
-        
-        /** ending position */
-        long end;
+        try
+        {
+            long pos = 0L;
 
+            if ( parentOffset != null )
+            {
+                pos = parentOffset.getEnd();
+            }
 
-        public EntryOffset( long start, long end )
-        {
-            this.start = start;
-            this.end = end;
-        }
+            ldifFile.seek( pos );
 
+            ldifFile.write( StringTools.getBytesUtf8( ldif + "\n" ) );
 
-        @Override
-        public String toString()
+            EntryOffset entryOffset = new EntryOffset( entryId, pos, ldifFile.getFilePointer() );
+            offsetMap.put( entryId, entryOffset );
+
+            return entryOffset;
+        }
+        catch ( IOException e )
         {
-            return "EntryOffset [start=" + start + ", end=" + end + "]";
+            throw new LdapException( e );
         }
     }
 
@@ -384,6 +428,29 @@ public class SingleFileLdifPartition ext
 
 
     /**
+     * gets all the EntryOffset objects whose start pos is greater than the given offset mark's start pos 
+     * 
+     * @param mark an EntryOffset object which is considered as a mark
+     * 
+     * @return a sorted set of EntryOffset objects
+     */
+    private Set<EntryOffset> greaterThan( EntryOffset mark )
+    {
+        Set<EntryOffset> gtSet = new TreeSet<EntryOffset>();
+
+        for ( EntryOffset o : offsetMap.values() )
+        {
+            if ( o.getStart() > mark.getStart() )
+            {
+                gtSet.add( o );
+            }
+        }
+
+        return gtSet;
+    }
+
+
+    /**
      * add the CSN and UUID attributes to the entry if they are not present
      */
     private void addMandatoryOpAt( Entry entry ) throws LdapException
@@ -400,3 +467,87 @@ public class SingleFileLdifPartition ext
         }
     }
 }
+
+/**
+ * a holder class for containing an entry's start and end offset positions
+ * in the LDIF file
+ */
+class EntryOffset implements Comparable<EntryOffset>
+{
+    /** starting position */
+    private long start;
+
+    /** ending position */
+    private long end;
+
+    /** entry id */
+    private Comparable id;
+
+
+    public EntryOffset( Comparable id, long start, long end )
+    {
+        this.start = start;
+        this.end = end;
+        this.id = id;
+    }
+
+
+    public int compareTo( EntryOffset o )
+    {
+        if ( end > o.end )
+        {
+            return 1;
+        }
+        else if ( end < o.end )
+        {
+            return -1;
+        }
+
+        return 0;
+    }
+
+
+    public long getStart()
+    {
+        return start;
+    }
+
+
+    public long getEnd()
+    {
+        return end;
+    }
+
+
+    public Comparable getId()
+    {
+        return id;
+    }
+
+
+    public void increaseOffsetsBy( long val )
+    {
+        start += val;
+        end += val;
+    }
+
+
+    public void decreaseOffsetsBy( long val )
+    {
+        start -= val;
+        end -= val;
+    }
+
+
+    public long length()
+    {
+        return ( end - start );
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return "EntryOffset [start=" + start + ", end=" + end + ", id=" + id + "]";
+    }
+}