directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1726718 - in /directory/apacheds/trunk: core-api/src/main/java/org/apache/directory/server/core/api/partition/ core-shared/src/main/java/org/apache/directory/server/core/shared/partition/ jdbm-partition/src/main/java/org/apache/directory/s...
Date Tue, 26 Jan 2016 00:12:50 GMT
Author: elecharny
Date: Tue Jan 26 00:12:49 2016
New Revision: 1726718

URL: http://svn.apache.org/viewvc?rev=1726718&view=rev
Log:
o Added the repair() method in the Partition interface
o Added the abstract doRepair() method in the AbstractPartition class
o Implemented the doRepair() method in the JdbmPartition
o Added a repair option in the UberJarMain class, and in the ApacheDSService class
o Added a test to check that the repair works

Modified:
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java
    directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
    directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
    directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
    directory/apacheds/trunk/service/pom.xml
    directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/ApacheDsService.java
    directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java
    directory/apacheds/trunk/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
    directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/avl/AvlPartition.java
    directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java
(original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java
Tue Jan 26 00:12:49 2016
@@ -111,6 +111,15 @@ public abstract class AbstractPartition
 
 
     /**
+     * {@inheritDoc}
+     */
+    public void repair() throws Exception
+    {
+        // Do nothing. It will be handled by the implementation classes
+    }
+
+
+    /**
      * Override this method to put your initialization code.
      */
     protected abstract void doDestroy() throws Exception;
@@ -118,12 +127,21 @@ public abstract class AbstractPartition
 
     /**
      * Override this method to put your initialization code.
-     * @throws Exception
+     * 
+     * @throws Exception If teh init failed
      */
     protected abstract void doInit() throws InvalidNameException, Exception;
 
 
     /**
+     * Override this method to implement a repair method
+     * 
+     * @throws Exception If the repair failed
+     */
+    protected abstract void doRepair() throws InvalidNameException, Exception;
+
+
+    /**
      * Calls {@link #doDestroy()} where you have to put your destroy code in,
      * and clears default properties.  Once this method is invoked, {@link #isInitialized()}
      * will return <tt>false</tt>.

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java
(original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java
Tue Jan 26 00:12:49 2016
@@ -104,10 +104,17 @@ public interface Partition
      * {@link #doInit()} returns without any errors.  {@link #destroy()} is called automatically
      * as a clean-up process if {@link #doInit()} throws an exception.
      *
-     * @throws Exception if initialization fails in any way
+     * @throws LdapException if initialization fails in any way
      */
     void initialize() throws LdapException;
 
+    /**
+     * Repair this partition. 
+     *
+     * @throws Exception if repair fails in any way
+     */
+    void repair() throws Exception;
+
 
     /**
      * Gets the normalized suffix as an Dn for this Partition after it has

Modified: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
(original)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
Tue Jan 26 00:12:49 2016
@@ -174,9 +174,30 @@ public class DefaultPartitionNexus exten
     }
 
 
-    /* (non-Javadoc)
-     * @see org.apache.directory.server.core.partition.PartitionNexus#initialize()
+    /**
+     * {@inheritDoc}
      */
+    @Override
+    public void repair() throws Exception
+    {
+        // Nothing to do
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doRepair() throws Exception
+    {
+        // Nothing to do
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     protected void doInit() throws Exception
     {
         // NOTE: We ignore ContextPartitionConfiguration parameter here.

Modified: directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
(original)
+++ directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
Tue Jan 26 00:12:49 2016
@@ -46,6 +46,8 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapSchemaViolationException;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
@@ -65,6 +67,7 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.server.xdbm.Index;
+import org.apache.directory.server.xdbm.ParentIdAndRdn;
 import org.apache.directory.server.xdbm.search.impl.CursorBuilder;
 import org.apache.directory.server.xdbm.search.impl.DefaultOptimizer;
 import org.apache.directory.server.xdbm.search.impl.DefaultSearchEngine;
@@ -122,6 +125,249 @@ public class JdbmPartition extends Abstr
             LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize,
id );
         }
     }
+    
+    
+    /**
+     * Rebuild the indexes 
+     */
+    private int rebuildIndexes() throws Exception
+    {
+        Cursor<Tuple<String, Entry>> cursor = getMasterTable().cursor();
+
+        int masterTableCount = 0;
+        int repaired = 0;
+
+        System.out.println( "Re-building indices..." );
+
+        boolean ctxEntryLoaded = false;
+
+        try
+        {
+            while ( cursor.next() )
+            {
+                masterTableCount++;
+                Tuple<String, Entry> tuple = cursor.get();
+                String id = tuple.getKey();
+
+                Entry entry = tuple.getValue();
+                
+                // Start with the RdnIndex
+                String parentId = entry.get( SchemaConstants.ENTRY_PARENT_ID_OID ).getString();
+                System.out.println( "Read entry " + entry.getDn() + " with ID " + id + "
and parent ID " + parentId );
+
+                Dn dn = entry.getDn();
+                
+                ParentIdAndRdn parentIdAndRdn = null;
+
+                // context entry may have more than one RDN
+                if ( !ctxEntryLoaded && getSuffixDn().getName().startsWith( dn.getName()
) )
+                {
+                    // If the read entry is the context entry, inject a tuple that have one
or more RDNs
+                    parentIdAndRdn = new ParentIdAndRdn( parentId, getSuffixDn().getRdns()
);
+                    ctxEntryLoaded = true;
+                }
+                else
+                {
+                    parentIdAndRdn = new ParentIdAndRdn( parentId, dn.getRdn() );
+                }
+
+                // Inject the parentIdAndRdn in the rdnIndex
+                rdnIdx.add( parentIdAndRdn, id );
+                
+                // Process the ObjectClass index
+                // Update the ObjectClass index
+                Attribute objectClass = entry.get( objectClassAT );
+
+                if ( objectClass == null )
+                {
+                    String msg = I18n.err( I18n.ERR_217, dn, entry );
+                    ResultCodeEnum rc = ResultCodeEnum.OBJECT_CLASS_VIOLATION;
+                    LdapSchemaViolationException e = new LdapSchemaViolationException( rc,
msg );
+                    //e.setResolvedName( entryDn );
+                    throw e;
+                }
+
+                for ( Value<?> value : objectClass )
+                {
+                    String valueStr = ( String ) value.getNormValue();
+
+                    if ( valueStr.equals( SchemaConstants.TOP_OC ) )
+                    {
+                        continue;
+                    }
+
+                    objectClassIdx.add( valueStr, id );
+                }
+                
+                // The Alias indexes
+                if ( objectClass.contains( SchemaConstants.ALIAS_OC ) )
+                {
+                    Attribute aliasAttr = entry.get( aliasedObjectNameAT );
+                    addAliasIndices( id, dn, new Dn( schemaManager, aliasAttr.getString()
) );
+                }
+                
+                // The entryCSN index
+                // Update the EntryCsn index
+                Attribute entryCsn = entry.get( entryCsnAT );
+
+                if ( entryCsn == null )
+                {
+                    String msg = I18n.err( I18n.ERR_219, dn, entry );
+                    throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION,
msg );
+                }
+
+                entryCsnIdx.add( entryCsn.getString(), id );
+
+                // The AdministrativeRole index
+                // Update the AdministrativeRole index, if needed
+                if ( entry.containsAttribute( administrativeRoleAT ) )
+                {
+                    // We may have more than one role
+                    Attribute adminRoles = entry.get( administrativeRoleAT );
+
+                    for ( Value<?> value : adminRoles )
+                    {
+                        adminRoleIdx.add( ( String ) value.getNormValue(), id );
+                    }
+
+                    // Adds only those attributes that are indexed
+                    presenceIdx.add( administrativeRoleAT.getOid(), id );
+                }
+
+                // And the user indexess
+                // Now work on the user defined userIndices
+                for ( Attribute attribute : entry )
+                {
+                    AttributeType attributeType = attribute.getAttributeType();
+                    String attributeOid = attributeType.getOid();
+
+                    if ( hasUserIndexOn( attributeType ) )
+                    {
+                        Index<Object, String> idx = ( Index<Object, String> )
getUserIndex( attributeType );
+
+                        // here lookup by attributeId is OK since we got attributeId from
+                        // the entry via the enumeration - it's in there as is for sure
+
+                        for ( Value<?> value : attribute )
+                        {
+                            idx.add( value.getNormValue(), id );
+                        }
+
+                        // Adds only those attributes that are indexed
+                        presenceIdx.add( attributeOid, id );
+                    }
+                }
+            }
+            
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+            System.out.println( "Exiting after fetching entries " + repaired );
+            throw e;
+        }
+        finally
+        {
+            cursor.close();
+        }
+        
+        return masterTableCount;
+    }
+    
+    
+    /**
+     * Update the children and descendant counters in the RDN index
+     */
+    private void updateRdnIndexCounters() throws Exception
+    {
+        Cursor<Tuple<String, Entry>> cursor = getMasterTable().cursor();
+
+        System.out.println( "Updating the RDN index counters..." );
+
+        try
+        {
+            while ( cursor.next() )
+            {
+                Tuple<String, Entry> tuple = cursor.get();
+
+                Entry entry = tuple.getValue();
+
+                // Update the parent's nbChildren and nbDescendants values
+                // Start with the RdnIndex
+                String parentId = entry.get( SchemaConstants.ENTRY_PARENT_ID_OID ).getString();
+                
+                if ( parentId != Partition.ROOT_ID )
+                {
+                    updateRdnIdx( parentId, ADD_CHILD, 0 );
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+            System.out.println( "Exiting, wasn't able to update the RDN index counters" );
+            throw e;
+        }
+        finally
+        {
+            cursor.close();
+        }
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doRepair() throws Exception
+    {
+        // Find the underlying directories
+        File partitionDir = new File( getPartitionPath() );
+        
+        // get the names of the db files
+        List<String> indexDbFileNameList = Arrays.asList( partitionDir.list( DB_FILTER
) );
+
+        // then add all index objects to a list
+        List<String> allIndices = new ArrayList<String>();
+
+        // Iterate on the declared indexes, deleting the old ones
+        for ( Index<?, String> index : getIndexedAttributes() )
+        {
+            // Index won't be initialized at this time, so lookup AT registry to get the
OID
+            AttributeType indexAT = schemaManager.lookupAttributeTypeRegistry( index.getAttributeId()
);
+            String oid = indexAT.getOid();
+            allIndices.add( oid );
+            
+            // take the part after removing .db from the
+            String name = oid + JDBM_DB_FILE_EXTN;
+            
+            // if the name doesn't exist in the list of index DB files
+            // this is a new index and we need to build it
+            if ( indexDbFileNameList.contains( name ) )
+            {
+                ((JdbmIndex<?>)index).close();
+                
+                File indexFile = new File( partitionDir, name );
+                indexFile.delete();
+                
+                // Recreate the index
+                ((JdbmIndex<?>)index).init( schemaManager, indexAT );
+            }
+        }
+
+        // Ok, now, rebuild the indexes.
+        int masterTableCount = rebuildIndexes();
+        
+        // Now that the RdnIndex has been rebuilt, we have to update the nbChildren and nbDescendants
values
+        // We loop again on the MasterTable 
+        updateRdnIndexCounters();
+        
+        // Flush the indexes on disk
+        sync();
+
+        System.out.println( "Total entries present in the partition " + masterTableCount
);
+        System.out.println( "Repair complete" );
+    }
 
 
     protected void doInit() throws Exception
@@ -223,11 +469,11 @@ public class JdbmPartition extends Abstr
             {
                 entryCache = cacheService.getCache( getId() );
 
-                int cacheSizeConfig = entryCache.getCacheConfiguration().getMaxElementsInMemory();
+                int cacheSizeConfig = (int)entryCache.getCacheConfiguration().getMaxEntriesLocalHeap();
 
                 if ( cacheSizeConfig < cacheSize )
                 {
-                    entryCache.getCacheConfiguration().setMaxElementsInMemory( cacheSize
);
+                    entryCache.getCacheConfiguration().setMaxEntriesLocalHeap( cacheSize
);
                 }
             }
 
@@ -326,7 +572,7 @@ public class JdbmPartition extends Abstr
         {
             idx.sync();
         }
-
+        
         // Sync the master table
         ( ( JdbmMasterTable ) master ).sync();
     }

Modified: directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
(original)
+++ directory/apacheds/trunk/mavibot-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/mavibot/MavibotPartition.java
Tue Jan 26 00:12:49 2016
@@ -112,8 +112,21 @@ public class MavibotPartition extends Ab
             LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize,
id );
         }
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doRepair() throws Exception
+    {
+        // Nothing to do
+    }
 
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected void doInit() throws Exception
     {

Modified: directory/apacheds/trunk/service/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service/pom.xml?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/service/pom.xml (original)
+++ directory/apacheds/trunk/service/pom.xml Tue Jan 26 00:12:49 2016
@@ -48,7 +48,7 @@
       <groupId>org.apache.directory.server</groupId>
       <artifactId>apacheds-service-builder</artifactId>
     </dependency>
-    
+        
     <dependency>
       <groupId>org.apache.directory.api</groupId>
       <artifactId>api-ldap-codec-standalone</artifactId>

Modified: directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/ApacheDsService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/ApacheDsService.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/ApacheDsService.java
(original)
+++ directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/ApacheDsService.java
Tue Jan 26 00:12:49 2016
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
@@ -61,6 +62,7 @@ import org.apache.directory.server.confi
 import org.apache.directory.server.config.beans.HttpServerBean;
 import org.apache.directory.server.config.beans.LdapServerBean;
 import org.apache.directory.server.config.beans.NtpServerBean;
+import org.apache.directory.server.config.beans.PartitionBean;
 import org.apache.directory.server.config.builder.ServiceBuilder;
 import org.apache.directory.server.config.listener.ConfigChangeListener;
 import org.apache.directory.server.core.api.CacheService;
@@ -218,6 +220,54 @@ public class ApacheDsService
     }
 
 
+    /**
+     * Try to repair the partitions. For each partition, we need its directory and its DN
+     *
+     * @param instanceLayout the on disk location's layout of the intance to be repaired
+     * @throws Exception If the repair failed
+     */
+    public void repair( InstanceLayout instanceLayout ) throws Exception
+    {
+        File partitionsDir = instanceLayout.getPartitionsDirectory();
+
+        if ( !partitionsDir.exists() )
+        {
+            LOG.info( "partition directory doesn't exist, creating {}", partitionsDir.getAbsolutePath()
);
+
+            if ( !partitionsDir.mkdirs() )
+            {
+                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
partitionsDir ) );
+            }
+        }
+
+        LOG.info( "Repairing partition dir {}", partitionsDir.getAbsolutePath() );
+
+        CacheService cacheService = new CacheService();
+        cacheService.initialize( instanceLayout );
+
+        initSchemaManager( instanceLayout );
+        DnFactory dnFactory = new DefaultDnFactory( schemaManager, cacheService.getCache(
"dnCache" ) );
+        initSchemaLdifPartition( instanceLayout, dnFactory );
+        initConfigPartition( instanceLayout, dnFactory, cacheService );
+        Set<? extends Partition> partitions = getDirectoryService().getPartitions();
+
+        // Iterate on the partitions to repair them
+        for ( Partition partition : partitions )
+        {
+            try
+            {
+                partition.repair();
+            }
+            catch ( Exception e )
+            {
+                System.out.println( "Failed to repair the partition " + partition.getId()
);
+                e.printStackTrace();
+                return;
+            }
+        }
+    }
+
+
     /**
      * Initialize the schema Manager by loading the schema LDIF files
      * 

Modified: directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java
(original)
+++ directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java
Tue Jan 26 00:12:49 2016
@@ -71,13 +71,15 @@ public class UberjarMain
         
         switch ( action )
         {
-            case START:
+            case START :
+                // Starts the server
                 LOG.debug( "Staring runtime" );
                 instance.start( instanceDirectory );
 
                 break;
 
-            case STOP:
+            case STOP :
+                // Stops the server
                 LOG.debug( "Stopping runtime" );
                 InstanceLayout layout = new InstanceLayout( instanceDirectory );
                 try ( Socket socket = new Socket( InetAddress.getLocalHost().getHostName(),
readShutdownPort( layout ) );
@@ -85,6 +87,14 @@ public class UberjarMain
                 {
                     writer.print( readShutdownPassword( layout ) );
                 }
+                
+                break;
+                
+            case REPAIR :
+                // Try to fix the JDBM database
+                LOG.debug( "Fixing the database runtime" );
+                instance.repair( instanceDirectory );
+                
                 break;
 
             default:
@@ -122,9 +132,14 @@ public class UberjarMain
     }
 
     
-    public void start( String... args )
+    /**
+     * Try to start the databases
+     *
+     * @param instanceDirectory The directory containing the server instance 
+     */
+    public void start( String instanceDirectory )
     {
-        InstanceLayout layout = new InstanceLayout( args[0] );
+        InstanceLayout layout = new InstanceLayout( instanceDirectory );
         
         // Creating ApacheDS service
         service = new ApacheDsService();
@@ -145,6 +160,43 @@ public class UberjarMain
         }
     }
 
+    
+    /**
+     * Try to repair the databases
+     *
+     * @param instanceDirectory The directory containing the server instance 
+     */
+    public void repair( String instanceDirectory )
+    {
+        InstanceLayout layout = new InstanceLayout( instanceDirectory );
+        
+        // Creating ApacheDS service
+        service = new ApacheDsService();
+        
+        try
+        {
+            service.start( layout );
+        }
+        catch ( Exception e )
+        {
+            return;
+        }
+
+        // Initializing the service
+        try
+        {
+            LOG.info( "Starting the service." );
+            service.repair( layout );
+            LOG.info( "Database repaired." );
+        }
+        catch ( Exception e )
+        {
+            LOG.error( "Failed to start the service.", e );
+            System.exit( 1 );
+        }
+    }
+    
+
     public void stop()
     {
         if ( service != null )
@@ -259,7 +311,7 @@ public class UberjarMain
     
     private static enum Action
     {
-        START, STOP;
+        START, STOP, REPAIR;
 
         public static Action fromString( String actionString )
         {

Modified: directory/apacheds/trunk/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service/src/test/java/org/apache/directory/server/UberJarMainTest.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
(original)
+++ directory/apacheds/trunk/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
Tue Jan 26 00:12:49 2016
@@ -24,12 +24,18 @@ import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.Calendar;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapConnectionConfig;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.server.constants.ServerDNConstants;
@@ -37,6 +43,7 @@ import org.apache.directory.server.core.
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import static org.junit.Assert.assertEquals;
 
 
 /**
@@ -86,40 +93,42 @@ public class UberJarMainTest
             FileUtils.deleteDirectory( instanceDirectory );
         }
     }
+    
+    
+    private LdapConnection createConnection() throws LdapException, UnknownHostException
+    {
+        LdapConnectionConfig configuration = new LdapConnectionConfig();
+        configuration.setLdapHost( InetAddress.getLocalHost().getHostName() );
+        configuration.setLdapPort( 10389 );
+        configuration.setName( ServerDNConstants.ADMIN_SYSTEM_DN );
+        configuration.setCredentials( PartitionNexus.ADMIN_PASSWORD_STRING );
+        configuration.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null
) );
+        LdapConnection connection = new LdapNetworkConnection( configuration );
+        connection.loadSchema();
 
-
-    /**
-     * Tests the creation of a new ApacheDS Service instance.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void serviceInstanceTest() throws Exception
-    {   
-        uberjarMain.start( new String[]
-            { instanceDirectory.toString() } );
+        // Binding on the connection
+        connection.bind();
+        
+        return connection;
+    }
+    
+    
+    private Thread createServer()
+    {
+        // First start the server to initialize the example partition 
+        uberjarMain.start( instanceDirectory.toString() );
 
         // Creating a separate thread for the connection verification
         Thread connectionVerificationThread = new Thread()
         {
             public void run()
             {
-                LdapNetworkConnection connection = null;
+                LdapConnection connection = null;
                 
                 try
                 {
                     // Creating a connection on the created server
-                    LdapConnectionConfig configuration = new LdapConnectionConfig();
-                    configuration.setLdapHost( InetAddress.getLocalHost().getHostName() );
-                    configuration.setLdapPort( 10389 );
-                    configuration.setName( ServerDNConstants.ADMIN_SYSTEM_DN );
-                    configuration.setCredentials( PartitionNexus.ADMIN_PASSWORD_STRING );
-                    configuration.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector(
null ) );
-                    connection = new LdapNetworkConnection( configuration );
-                    connection.loadSchema();
-
-                    // Binding on the connection
-                    connection.bind();
+                    connection = createConnection();
 
                     // Looking for the Root DSE entry
                     Entry rootDseEntry = connection.lookup( Dn.ROOT_DSE );
@@ -149,6 +158,20 @@ public class UberJarMainTest
                 }
             };
         };
+
+        return connectionVerificationThread;
+    }
+
+
+    /**
+     * Tests the creation of a new ApacheDS Service instance.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void serviceInstanceTest() throws Exception
+    {   
+        Thread connectionVerificationThread = createServer();
         
         // Starting the connection verification thread
         // and waiting for the termination of it
@@ -161,4 +184,215 @@ public class UberJarMainTest
             fail();
         }
     }
+
+
+    /**
+     * Tests the repair of an existing ApacheDS Service instance.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void repairTest() throws Exception
+    {   
+        // First start the server to initialize the example partition 
+        Thread connectionVerificationThread = createServer();
+        
+        // Starting the connection verification thread
+        // and waiting for the termination of it
+        connectionVerificationThread.start();
+        connectionVerificationThread.join();
+
+        // Checking if verification is successful
+        if ( !verified )
+        {
+            fail();
+        }
+        
+        // Add a few entries to create a more complex hierarchy
+        // We will have :
+        // dc=example,dc=com
+        //    ou=people
+        //      ou=committers
+        //        cn=emmanuel
+        //        cn=kiran
+        //        cn=stefan
+        //        cn=radovan
+        //      ou=pmcs
+        //        cn=emmanuel
+        //        cn=kiran
+        //        cn=stefan
+        //   ou=groups
+        //     cn=users
+        LdapConnection connection = createConnection();
+        
+        // First level
+        Entry people = new DefaultEntry( 
+            "ou=People,dc=example,dc=com",
+            "objectClass: organizationalUnit",
+            "objectClass: top",
+            "ou: People"
+            );
+        
+        connection.add( people );
+        
+        Entry groups = new DefaultEntry( 
+            "ou=Groups,dc=example,dc=com",
+            "objectClass: organizationalUnit",
+            "objectClass: top",
+            "ou: Groups"
+            );
+        
+        connection.add( groups );
+        
+        // Second level
+        Entry committers  = new DefaultEntry( 
+            "ou=Committers,ou=people,dc=example,dc=com",
+            "objectClass: organizationalUnit",
+            "objectClass: top",
+            "ou: Committers"
+            );
+
+        connection.add( committers );
+
+        Entry pmcs  = new DefaultEntry( 
+            "ou=Pmcs,ou=people,dc=example,dc=com",
+            "objectClass: organizationalUnit",
+            "objectClass: top",
+            "ou: Pmcs"
+            );
+
+        connection.add( pmcs );
+
+        Entry users  = new DefaultEntry( 
+            "ou=Users,ou=people,dc=example,dc=com",
+            "objectClass: organizationalUnit",
+            "objectClass: top",
+            "ou: Users"
+            );
+
+        connection.add( users );
+
+        // Third level, committers
+        Entry emmanuelCommitter  = new DefaultEntry( 
+            "cn=emmanuel,ou=Committers,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: emmanuel",
+            "sn: Emmanuel Lecharny"
+            );
+
+        connection.add( emmanuelCommitter );
+
+        Entry kiranCommitter  = new DefaultEntry( 
+            "cn=kiran,ou=Committers,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: kiran",
+            "sn: Kiran Ayyagari"
+            );
+
+        connection.add( kiranCommitter );
+
+        Entry stefanCommitter  = new DefaultEntry( 
+            "cn=stefan,ou=Committers,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: stefan",
+            "sn: Stefan Seelmann"
+            );
+
+        connection.add( stefanCommitter );
+        
+        Entry radovanCommitter  = new DefaultEntry( 
+            "cn=radovan,ou=Committers,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: radovan",
+            "sn: Radovan Semancik"
+            );
+
+        connection.add( radovanCommitter );
+
+        // Third level, PMCs
+        Entry emmanuelPmc = new DefaultEntry( 
+            "cn=emmanuel,ou=Pmcs,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: emmanuel",
+            "sn: Emmanuel Lecharny"
+            );
+
+        connection.add( emmanuelPmc );
+
+        Entry kiranPmc = new DefaultEntry( 
+            "cn=kiran,ou=Pmcs,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: kiran",
+            "sn: Kiran Ayyagari"
+            );
+
+        connection.add( kiranPmc );
+
+        Entry stefanPmc = new DefaultEntry( 
+            "cn=stefan,ou=Pmcs,ou=people,dc=example,dc=com",
+            "objectClass: person",
+            "objectClass: top",
+            "cn: stefan",
+            "sn: Stefan Seelmann"
+            );
+
+        connection.add( stefanPmc );
+        
+        // Now, check that we have 13 entries
+        int entryCount = 0;
+        
+        EntryCursor cursor = connection.search( "dc=example, dc=com","(ObjectClass=*)", SearchScope.SUBTREE,
"*" );
+        
+        while ( cursor.next() )
+        {
+            cursor.get();
+            entryCount++;
+        }
+        
+        assertEquals( 13, entryCount );
+
+        // Stop the server
+        uberjarMain.stop();
+
+        // Try to repair it
+        uberjarMain.repair( instanceDirectory.toString() );
+
+        // Stop the server again
+        uberjarMain.stop();
+        
+        // And restart it
+        connectionVerificationThread = createServer();
+        
+        // Starting the connection verification thread
+        // and waiting for the termination of it
+        connectionVerificationThread.start();
+        connectionVerificationThread.join();
+
+        // Checking if verification is successful
+        if ( !verified )
+        {
+            fail();
+        }
+
+        // Check the content
+        connection = createConnection();
+
+        entryCount = 0;
+        
+        cursor = connection.search( "dc=example, dc=com","(ObjectClass=*)", SearchScope.SUBTREE,
"*" );
+        
+        while ( cursor.next() )
+        {
+            cursor.get();
+            entryCount++;
+        }
+        
+        assertEquals( 13, entryCount );
+    }
 }

Modified: directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/avl/AvlPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/avl/AvlPartition.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/avl/AvlPartition.java
(original)
+++ directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/avl/AvlPartition.java
Tue Jan 26 00:12:49 2016
@@ -74,11 +74,22 @@ public class AvlPartition extends Abstra
     {
         super( schemaManager, dnFactory );
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doRepair() throws Exception
+    {
+        // Nothing to do
+    }
 
-
+    
     /**
      * {@inheritDoc}
      */
+    @Override
     protected void doInit() throws Exception
     {
         if ( !initialized )

Modified: directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java?rev=1726718&r1=1726717&r2=1726718&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
(original)
+++ directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
Tue Jan 26 00:12:49 2016
@@ -551,6 +551,16 @@ public abstract class AbstractBTreeParti
     /**
      * {@inheritDoc}
      */
+    public void repair() throws Exception
+    {
+        // Do nothing by default
+        doRepair();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     protected void doInit() throws Exception
     {
         // First, inject the indexed attributes if any




Mime
View raw message