protected void doInit()

in jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java [398:641]


    protected void doInit() throws LdapException
    {
        if ( !initialized )
        {
            BaseRecordManager base;

            // setup optimizer and registries for parent
            if ( !optimizerEnabled )
            {
                setOptimizer( new NoOpOptimizer() );
            }
            else
            {
                setOptimizer( new DefaultOptimizer( this ) );
            }

            EvaluatorBuilder evaluatorBuilder = new EvaluatorBuilder( this, schemaManager );
            CursorBuilder cursorBuilder = new CursorBuilder( this, evaluatorBuilder );

            setSearchEngine( new DefaultSearchEngine( this, cursorBuilder, evaluatorBuilder, getOptimizer() ) );

            // Create the underlying directories (only if needed)
            File partitionDir = new File( getPartitionPath() );
            
            if ( !partitionDir.exists() && !partitionDir.mkdirs() )
            {
                throw new LdapOtherException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECTORY, partitionDir ) );
            }

            // First, check if the file storing the data exists
            String path = partitionDir.getPath() + File.separator + id;

            try
            {
                base = new BaseRecordManager( path );
                TransactionManager transactionManager = base.getTransactionManager();
                transactionManager.setMaximumTransactionsInLog( 2000 );
                
                // prevent the OOM when more than 50k users are loaded at a stretch
                // adding this system property to make it configurable till JDBM gets replaced by Mavibot
                String cacheSizeVal = System.getProperty( "jdbm.recman.cache.size", "100" );
                
                int recCacheSize = Integer.parseInt( cacheSizeVal );
                
                LOG.info( "Setting CacheRecondManager's cache size to {}", recCacheSize );
                
                recMan = new CacheRecordManager( base, new MRU( recCacheSize ) );
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }

            // Iterate on the declared indexes
            List<String> allIndices = new ArrayList<>();
            List<Index<?, String>> indexToBuild = new ArrayList<>();

            for ( Index<?, String> index : getIndexedAttributes() )
            {
                String oid = schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() ).getOid();
                allIndices.add( oid );
                
                // if the name doesn't exist in the database
                // this is a new index and we need to build it
                try
                {
                    // Check the forward index only (we suppose we never will add a reverse index later on)
                    String forwardIndex = oid + "_forward";
                    
                    if ( recMan.getNamedObject( forwardIndex ) == 0 )
                    {
                        // The index does not exist in the database, we need to build it
                        indexToBuild.add( index );
                    }
                }
                catch ( IOException ioe )
                {
                    throw new LdapOtherException( ioe.getMessage(), ioe );
                }
            }

            /*
            // get all index db files first
            File[] allIndexDbFiles = partitionDir.listFiles( DB_FILTER );

            // get the names of the db files also
            List<String> indexDbFileNameList = Arrays.asList( partitionDir.list( DB_FILTER ) );

            // then add all index objects to a list
            List<String> allIndices = new ArrayList<>();

            List<Index<?, String>> indexToBuild = new ArrayList<>();
            
            // Iterate on the declared indexes
            for ( Index<?, String> index : getIndexedAttributes() )
            {
                // Index won't be initialized at this time, so lookup AT registry to get the OID
                String oid = schemaManager.lookupAttributeTypeRegistry( index.getAttributeId() ).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 ) )
                {
                    indexToBuild.add( index );
                }
            }
            */

            // Initialize the indexes
            super.doInit();

            if ( cacheSize < 0 )
            {
                cacheSize = DEFAULT_CACHE_SIZE;
                LOG.debug( "Using the default entry cache size of {} for {} partition", cacheSize, id );
            }
            else
            {
                LOG.debug( "Using the custom configured cache size of {} for {} partition", cacheSize, id );
            }

            // Create the master table (the table containing all the entries)
            try
            {
                master = new JdbmMasterTable( recMan, schemaManager );
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }

            if ( !indexToBuild.isEmpty() )
            {
                buildUserIndex( beginReadTransaction(), indexToBuild );
            }

            entryCache = Caffeine.newBuilder().maximumSize( cacheSize ).build();

            // Initialization of the context entry
            if ( ( suffixDn != null ) && ( contextEntry != null ) )
            {
                Dn contextEntryDn = contextEntry.getDn();

                // Checking if the context entry DN is schema aware
                if ( !contextEntryDn.isSchemaAware() )
                {
                    contextEntryDn = new Dn( schemaManager, contextEntryDn );
                }

                // We're only adding the entry if the two DNs are equal
                if ( suffixDn.equals( contextEntryDn ) )
                {
                    // Looking for the current context entry
                    Entry suffixEntry;
                    LookupOperationContext lookupContext = new LookupOperationContext( null, suffixDn );
                    lookupContext.setPartition( this );
                    
                    try ( PartitionTxn partitionTxn = beginReadTransaction() )
                    {
                        lookupContext.setTransaction( partitionTxn );
                        suffixEntry = lookup( lookupContext );
                    }
                    catch ( IOException ioe )
                    {
                        throw new LdapOtherException( ioe.getMessage(), ioe );
                    }

                    // We're only adding the context entry if it doesn't already exist
                    if ( suffixEntry == null )
                    {
                        // Checking of the context entry is schema aware
                        if ( !contextEntry.isSchemaAware() )
                        {
                            // Making the context entry schema aware
                            contextEntry = new DefaultEntry( schemaManager, contextEntry );
                        }

                        // Adding the 'entryCsn' attribute
                        if ( contextEntry.get( SchemaConstants.ENTRY_CSN_AT ) == null )
                        {
                            contextEntry.add( SchemaConstants.ENTRY_CSN_AT, new CsnFactory( 0 ).newInstance()
                                .toString() );
                        }

                        // Adding the 'entryUuid' attribute
                        if ( contextEntry.get( SchemaConstants.ENTRY_UUID_AT ) == null )
                        {
                            String uuid = UUID.randomUUID().toString();
                            contextEntry.add( SchemaConstants.ENTRY_UUID_AT, uuid );
                        }

                        // And add this entry to the underlying partition
                        PartitionTxn partitionTxn = null;
                        AddOperationContext addContext = new AddOperationContext( null, contextEntry );
                        
                        try
                        {
                            partitionTxn = beginWriteTransaction();
                            addContext.setTransaction( partitionTxn );

                            add( addContext );
                            partitionTxn.commit();
                        }
                        catch ( LdapException le )
                        {
                            if ( partitionTxn != null )
                            {
                                try
                                { 
                                    partitionTxn.abort();
                                }
                                catch ( IOException ioe )
                                {
                                    throw new LdapOtherException( ioe.getMessage(), ioe );
                                }
                            }
                            
                            throw le;
                        }
                        catch ( IOException ioe )
                        {
                            try
                            { 
                                partitionTxn.abort();
                            }
                            catch ( IOException ioe2 )
                            {
                                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
                            }

                            throw new LdapOtherException( ioe.getMessage(), ioe );
                        }
                    }
                }
            }

            // We are done !
            initialized = true;
        }
    }